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>
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
I wouldn't use Action<T> for this signature because it comes with an implicit constraint; namely, it mandates a mutable type. Instead, I'd us Func<T, T>, which works quite nicely with both mutable and immutable types.
ReplyDeleteThanks for the response. I thought about using Func<T,T> but that could potentially bypass the Factory entirely. I decided to go with Action<T> because it is a transformation of the object in place. I can see where someone else might choose differently, though. Using Func<T,T> would be a good way to build it compositionally using the Decorator pattern.
Delete