Monday, December 24, 2012

Using an Action in a Factory

We’ve all seen the Factory (or Factory Method) Pattern. The Factory Pattern is used to encapsulate the creational logic for a set of related classes, classes that implement a particular interface or inherit from the same base class.

From Wikipedia:
The factory method pattern is an object-oriented creational design pattern to implement the concept of factories and deals with the problem of creating objects (products) without specifying the exact class of object that will be created. The essence of this pattern is to "Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
One way to implement the pattern is to use a Enum or some other designator to specify the type of object to be created.  The factory method then uses either if statements or a switch statement to create the proper type of object or decorate it appropriately based on the setting of the designator. This works well when the creational logic is simple or the number of things created is small. Alternatively, you could have a factory method per type, but that can have the effect of moving the selection logic to the calling class which defeats the purpose.

In answering a recent StackOverflow question I ran across this issue and it made me think of alternative ways that you could handle this.  Using an Action<T> as the designator seemed to me to be a perfect solution in the case in question.  Using an Action allows you to separate the creational logic for each item into a separate method, avoiding overly long switch or set of if statements.

For example:

public static class WeaponFactory
{
    public static IWeapon Create<T>(Action<T> decorator) where T : IWeapon, new()
    {
        var weapon = new T();
        decorator(weapon);
        return weapon;
    }

    public static void SwordOfDestiny(Sword sword)
    {
        sword.Damage = DamageLevel.Infinite;
    }

    public static void NormalSword(Sword sword)
    {
    }

    public static void TinSword(Sword sword)
    {
        sword.Damage = DamageLevel.Minor;
    }
}

Invoked as:

var weapon = WeaponFactory.Create(WeaponFactory.SwordOfDestiny);

Using this allows you to keep the creational logic completely separated and avoid the long switch statement. I’d probably use in conjunction with a dictionary, say Dictionary<Person,Action<IWeapon>> to give me the simplicity of tying the type of the thing to be created to some other aspect/setting and yet still be able to use the decorator pattern within the factory.