Object Oriented Programming Patterns for Geeks
The Provider Factory
This isn't a GoF pattern in and of itself. However because this crops up so often I felt it deserved a place here. This pattern makes use of the Bridge pattern to allow the 'concrete creator' to exhibit different characteristics depending on the 'implementor' or 'provider' fed to it.
The above in english essentially means that you can interchange the machinery of the factory depending on what product you want to create while keeping the basic structure of the factory and it's use intact.
This pattern actually is not too far removed from the Abstract Factory, except where-as with the Abstract Factory pattern you supply a Concrete Creator to a client object for it to consume and use as required, this variation supplies an 'implementor' which (most likely) contains a Concrete Creator for the factory to use when you ask it to manufacture an object for you. You can then if you so choose, supply the Factory that utiliises the supplied Implementor to a client object as per Abstract Factory.
This pattern is used in DATS to supply DAL operations to the library.
namespace ooppatterns
{
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main( string[] args )
{
List<IAbstractProduct> aList = new List<IAbstractProduct>();
MethodFactory factory = new MethodFactory();
factory.Implementor = new ContextProviderA();
for ( int i = 0; i < 35; i++ )
{
if(i == 12)
factory.Implementor = new ContextProviderB();
else if( i==20)
factory.Implementor = new ContextProviderA();
else if ( i == 30 )
factory.Implementor = new ContextProviderB();
aList.Add( factory.Create( i ) );
}
foreach ( IAbstractProduct ID in aList )
ID.DoSomething();
Console.ReadLine();
}
}
// Providers or Implementor's from the Bridge pattern
interface IProviderFactory
{
IAbstractFactory GetConcreteFactory( );
}
class ContextProviderA : IProviderFactory
{
public IAbstractFactory GetConcreteFactory()
{
return new ConcreteFactoryA();
}
}
class ContextProviderB : IProviderFactory
{
public IAbstractFactory GetConcreteFactory( )
{
return new ConcreteFactoryB();
}
}
// Factories...
interface IAbstractFactory
{
IAbstractProduct CreateProduct( int manufactureCriteria );
}
class ConcreteFactoryA : IAbstractFactory
{
public IAbstractProduct CreateProduct( int manufactureCriteria )
{
if ( manufactureCriteria % 15 == 0 )
return new Example01( "This is created using MOD 15 FIZZBANG" );
if ( manufactureCriteria % 5 == 0 )
return new Example02( "This is created using MOD 5 FIZZ" );
if ( manufactureCriteria % 3 == 0 )
return new Example03( "This is created using MOD 3 BANG" );
return new Example00( manufactureCriteria.ToString() );
}
}
class ConcreteFactoryB : IAbstractFactory
{
public IAbstractProduct CreateProduct( int manufactureCriteria )
{
if ( manufactureCriteria % 13 == 0 )
return new Example03( "This is created using MOD 13 Wibble" );
if ( manufactureCriteria % 10 == 0 )
return new Example01( "This is created using MOD 10 Wobble" );
if ( manufactureCriteria % 7 == 0 )
return new Example02( "This is created using MOD 7 Wubble" );
return new Example00( manufactureCriteria.ToString() );
}
}
// 'Abstraction' or 'Refined Abstraction' from the Bridge pattern
class MethodFactory
{
private IProviderFactory _myPF;
public IProviderFactory Implementor
{
set
{
this._myPF = value;
}
}
public IAbstractProduct Create( int manufactureCriteria )
{
if ( this._myPF == null )
throw new NullReferenceException();
IAbstractFactory IAF = this._myPF.GetConcreteFactory();
return IAF.CreateProduct( manufactureCriteria );
}
}
// Products...
interface IAbstractProduct
{
void DoSomething();
}
// Concrete Product 00
class Example00 : IAbstractProduct
{
private string _value;
public Example00( string value )
{
this._value = value;
}
public void DoSomething()
{
Console.WriteLine( "Example00 : {0}", this._value );
}
}
// Concrete Product 01
class Example01 : IAbstractProduct
{
private string _value;
public Example01( string value )
{
this._value = value;
}
public void DoSomething()
{
Console.WriteLine( "Example01 : {0}", this._value );
}
}
// Concrete Product 02
class Example02 : IAbstractProduct
{
private string _value;
public Example02( string value )
{
this._value = value;
}
public void DoSomething()
{
Console.WriteLine("Example02 : {0}", this._value );
}
}
// Concrete Product 03
class Example03 : IAbstractProduct
{
private string _value;
public Example03( string value )
{
this._value = value;
}
public void DoSomething()
{
Console.WriteLine( "Example03 : {0}", this._value );
}
}
}