I hope my last post left you curious enough to come back ;) . Before diving into the patterns I mentioned, I need to talk a bit about factories. Pave the way, so to speak.
I’ll assume that you know what a factory is — if smoking chimneys cross you mind you may leave right now ;) — but since factories and the related patterns come in various flavours I should clarify what I define as „a Factory“ (if only for this post):
To put it simply: A factory is an object that takes a name (somehow describing the object instance I need) and returns a reference to an object or interface. Period. Well, OK, let’s assume there is some configuration file that maps names to types.
In more detail…
Since our factory shall take names and map them to types it will need some kind of dictionary, presumably supplied as config file, say something like this:
<add key=“Name1” value=“Namspace1.Type1, Assembly1” />
<add key=“Name2” value=“Namspace2.Type2, Assembly2” />
Once we have the type, we need to create an object. In .NET creating objects dynamically should be done via the Activator class.
Activator “Contains methods to create types of objects locally or remotely, or obtain references to existing remote objects.” and is the recommended way to do just that. The AppDomain class also contains methods to create objects, as do other classes, but they usually call Activator themselves.
It is also possible to invoke the constructor directly via reflection. This is however not recommended.
Assuming the configuration has been loaded and put in some dictionaries, the core method of our homegrown factory looks somewhat like this (error handling omitted for brevity):
public object Create(string name)
string assembly= _nameToAssembly[name];
string type= _nameToType[name];
ObjectHandle handle = Activator.CreateInstance(assembly, type);
The usage would look like this (assuming a respective singleton implementation of the factory):
object o= Factory.Instance.Create(“Name1”);
// typed access
IMyInterface t= (IMyInterfacse)Factory.Instance.Create(“Name2”);
Conceptually there is really nothing more to it. Of course some code to fill the hash tables and some error handling, but that’s all. Well, that’s all that’s needed for the purposes I have currently in mind, but certainly not all that is possible. Let’s look at some enhancements.
The first improvements to come up with are type safety and getting rid of the name argument, as it is prone to typos. A common use case for the factory is as follows: I have an interface and need an object that implements this interface. Wherever and whenever I ask for an implementation of that interface I get an object of a certain type — configurable but nevertheless always of the same type. In other words, the interface type is in itself a sufficient key and a type safe helper method taking that into account may look like this:
public static class Factory<ObjectType>
static public ObjectType Create()
Complemented with a configuration that mapps interface type names to implementation classes:
value=“SDX.MyApp.Business.Components.AccountService, SDX.MyApp.Business.Components” />
value=“SDX.MyApp.Business.Components.CustomerService, SDX.MyApp.Business.Components” />
The usage would now be more convenient:
IMyInterface o= Factory<IMyInterface>.Create();
The following improvements are definitely for more sophisticated usage scenarios than the ones I have in mind. But since this post is dedicated to factories in general I think I should to mention them anyway.
Here are some strategies to change or improve the object creation and initialization:
- The factory could decide not to create a new object with every call, rather it could return the previously created instance again (effectively implementing a singleton mechanism). This requires the object to be reentrant and stateless, but if that’s the case, this will be a big improvement in terms of memory and performance.
- A pooling approach could be implemented for objects that are particular expensive to create. It would require a base class that would implement IDisposable in a way that the object is not destructed but put back into the pool.
- Talking about performance, creating objects dynamically is not exactly the most efficient thing to do. In fact it takes about 10^3 times more time than direct calls to new. If objects knew themselves how to create new instances of the same type (which is something ICloneable could help with), the factory could leverage this to implement a prototype mechanism: When an object is requested for the first time, a prototype instance is created dynamically and stored in an internal list. Rather than returning it, it is asked to create a new instance (efficiently via the mentioned interface) which is returned. Subsequent calls will use the prototype in the same way, resulting in a big performance boost for objects that are requested quite often.
- It is possible to specify not only the type in the config file, but also constructor parameters. These parameters could reference other objects also configured to be created by the factory. This would result in not only one object being created but a whole object graph. But this is no little amount of work to do and exactly what factory frameworks do.
If the last suggestion regarding constructor arguments in the config file is something you like, then Spring.NET may be the tool for you. It supports not only constructor arguments, but property setters as well. It handles references to other configured objects and some other cases, such as collections. And it supports the singleton mechanism out of the box (as I am painfully aware of). It lacks prototype or pooling support, but that could easily be build on top of it (as on every other factory framework).
On other hand, Spring.NET (when I last looked at it) does not follow the recommendation to create objects via the Activator class. Rather it tries to find an appropriate constructor (which does not always succeed) and invoke it directly. It also creates all singleton objects right away, which may cause problems of its own.
Short factory framework list:
- Spring.NET is certainly not a bad choice if you need the flexibility. And it goes beyond a pure factory framework (even if it is still behind the java spring framework), but I have no experience with those features, sorry.
- I have not worked with MicroKernel/Windsor yet (certainly I have not looked at the code), but the documentation looks interesting enough to give it a try.
- The Object Builder, being written by the Microsoft patterns and practices group and used by the Enterprise Library, may be something to keep an eye on. It appeared a bit like a second class citizen or a pure necessity when it came out; but together with the Policy Injection Application Block (PIAB) it may gain more relevance.
- Wikipedia lists some more options but I have no knowledge about them.
Lastly let me point out that if your demands are as simple as described in the first part of this post, it is perfectly feasible to write a factory yourself. It won’t take weeks and it certainly has the benefit of not introducing external dependencies. OK, and it might be fun, too.
In my next post I will employ the factory as a means for layer separation and I will add some additional patterns built on top of a factory. This should (hopefully) highlight the bennefits of using a factory.