Factory Sample: Enumerations or Types?

When implementing a factory or a simple factory, what would be against using a type instead of Enum to specify a class to instantiate?

for example

public class SimpleFactory { public static ITest Create(Type type) { if (type == typeof(ConcreteTest1)) return new ConcreteTest1(); if (type == typeof(ConcreteTest2)) return new ConcreteTest2(); throw new Exception("Invalid type"); } } 
+6
c # design-patterns
source share
6 answers

Using an enumeration is more restrictive, which means that it is less likely that the user will try to use your factory with an unsupported type.

In my opinion, when defining an API, it’s useful to do everything possible to discourage usage patterns that will throw exceptions. The Type permission in this case opens up millions of ways to call your function, which will result in:

 throw new Exception("Invalid type"); 

Using an enumeration will eliminate this. The only way that enum was thrown would be if the user did something obscure.

+15
source share

Factories are only useful if they are configuring or initializing your facilities to bring them to the correct state. I would not worry about the factory if all he does is new and returned objects.

I would create a factory for each class hierarchy. For example:

 public abstract class Vehicle {} public class Car : Vehicle {} public class Truck : Vehicle {} public class VehicleFactory { public Vehicle CreateVehicle<T>() where T : Vehicle { // Get type of T and delegate creation to private methods } } 
+4
source share

if you want a fool proof factory, you must create one specific factory for each particular type. This class does not follow the open-closed principle: every time you get a new concrete type, you must re-edit this class.

IMHO it is better to use inheritance, one specific class factory for each specific type.

+2
source share

I would prefer to use a general restriction for the reason that having an enumeration is just to indicate which particular object seems redundant to me, and using the type you described, you violate the Open / Closed principle. What I would do differently than what you did there restrains your type so that only valid types can be passed.

I will give an example in C # using generics.

 public class SimpleFactory { public static ITest Create<T>() where T: ITest, new() { return new T(); } } 

Then you must implement IConcreteTest with ConcreteTest1 and ConcreteTest2, and you can use the factory as follows:

 ConcreteTest1 test1 = SimpleFactory.Create<ConcreteTest1>(); 
+2
source share

If you want to create by type, you can simply use Activator.CreateInstance(Type t) . Wrap it in a template method to restrict it to an interface, such as Create<T> where T:ITest .

+1
source share

I think the biggest problem I encountered is that the goal of the factory is for the client code to be able to create a derived instance of the object without knowing the details of the type being created (more precisely, the details of how to instantiate, but if everything is done correctly, the caller does not need to know any of the finer details except what is provided by the base class).

Using type information extracted from a derived type still requires the caller to have some intimate knowledge of what type he wants to create, making updating and maintenance difficult. By replacing the Enum type (or string, int, etc.), you can update the factory without updating the calling code to be aware of the new derived types.

I suppose it can be argued that the type name can be read as a string from the configuration file, database, etc., and the type information is determined using Reflections (in .NET) or RTTI (in C ++), but I think that this is the best case for simply using a type string as your identifier, as it will serve the same purpose effectively.

+1
source share

All Articles