2007 |
Section 1, Chapter 2 |
Factory Pattern
Concept
Factories use a base class type to create a class instance. This type can be in the form of either an abstraction or an interface, and based on that type, via creational methods, the factory renders a functional class that inherits or implements this type.
Use
You might use a Factory pattern if you had a lot of creational logic for instances of a class type strewn throughout your code base. You might wish to consolidate this logic into one place for uniformity and maintainability.
Design
Factories can be static or creation only, or repositories, which both create and store references to the created products. But in general, factories provide a way to house the creational aspects of class types.
The Factory pattern has two main components: the Factory and the Product. The factory class is the class that renders the product class. The product class is the class containing data or functionality and is part of a series of class types that can be rendered from a factory method as an instance of an abstract type.
Explanation of the UML class diagram:
Illustration
Reflective algorithm
reflection in .NET
Type type = typeof(GolfSuit);
Suit suit = (Suit)Activator.CreateInstance(type));
Or
Type type = typeof(GolfSuit);
ConstructorInfo info = type.GetConstructor(new Type[]{});
Suit suit = (Suit)info.Invoke(new object[]{}));
reflection in Java
Constructor con = Class.forName("GolfSuit").getConstructor(null);
return con.newInstance(null);
Reflective Solution example
public sealed class SuitFactory
{
private Hashtable _registered = new Hashtable();
private Hashtable _loaded = new Hashtable();
public Suit CreateSuit(SuitType suitType)
{
if(_loaded[suitType] == null)
Load();
return (Suit)_loaded[suitType];
}
public void Register(SuitType suitType, Type type)
{
_registered.Add(suitType, type);
}
private void Load()
{
foreach(DictionaryEntry obj in _registered)
{
Type type = (Type)obj.Value;
ConstructorInfo info = type.GetConstructor(new Type[]{});
if(!_loaded.ContainsKey(obj.Key))
//checks if the class is loaded
_loaded.Add(obj.Key,(Suit)info.Invoke(new object[]{}));
//we can use direct reflection in .NET or an activator
//_loaded.Add(obj.Key,(Suit)Activator.CreateInstance(type));
}
}
}
SuitFactory factory = new SuitFactory();
factory.Register(SuitType.Armani, typeof(Armani));
factory.Register(SuitType.GolfSuit, typeof(GolfSuit));
factory.Register(SuitType.PlaidBusinessSuit, typeof(PlaidBusinessSuit));
factory.Register(SuitType.StripedBusinessSuit, typeof(StripedBusinessSuit));
Suit suit = factory.CreateSuit(SuitType.StripedBusinessSuit);
Inherited algorithm
December 2007 |
Section 2, Chapter 5 |
The client declares a Product variable but calls a FactoryMethod to instantiate it. This defers the decision as to which particular product to create.
IProduct | The interface for products |
ProductA and ProductB | Classes that implement IProduct |
Creator | Provides the FactoryMethod |
FactoryMethod | Decides which class to instantiate |
2016 |
Chapter 12 |
GoF Definition: Define an interface for creating an object, but let subclasses decide which class to instantiate. The factory method lets a class defer instantiation to subclasses.
abstract class IAnimalFactory {
/*if we cannot instantiate in later stage, we'll throw exception*/
public abstract IAnimal GetAnimalType(String type) throws Exception;
}
class ConcreteFactory extends IAnimalFactory {
@Override
public IAnimal GetAnimalType(String type) throws Exception
{
switch (type)
{
case "Duck":
return new Duck();
case "Tiger":
return new Tiger();
default:
throw new Exception("Animal type : " + type + " cannot be instantiated");
}
}
}
class FactoryPatternEx
{
public static void main(String[] args) throws Exception
{
System.out.println("***Factory Pattern Demo***\n");
IAnimalFactory animalFactory = new ConcreteFactory();
IAnimal DuckType = animalFactory.GetAnimalType("Duck");
DuckType.Speak();
IAnimal TigerType = animalFactory.GetAnimalType("Tiger");
TigerType.Speak();
//There is no Lion type. So, an exception will be thrown
IAnimal LionType = animalFactory.GetAnimalType("Lion");
LionType.Speak();
}
}
March 25, 2002 |
Chapter 16 |
Recognizing Factory Method
To summarize, the signs that FACTORY METHOD is at work are that an operation:
- Creates a new object
- Returns a type that is an abstract class or an interface
- Is implemented by several classes
But the spirit of FACTORY METHOD is that the object creator makes a choice about which of several possible classes to instantiate for the client.
The point of the FACTORY METHOD pattern, which the iterator() method exemplifies well, is that clients of the method need not know which class to instantiate.
References:
Chapter 16