Abstract Factory is a tremendously useful pattern when used with Dependency Injection (DI). While I've repeatedly described how it can be used to solve various problems in DI, apparently I've never described how to implement one. As a comment to an older blog post of mine, Thomas Jaskula asks how I'd implement the IOrderShipperFactory.

To stay consistent with the old order shipper scenario, this blog post outlines three alternative ways to implement the IOrderShipperFactory interface.

To make it a bit more challenging, the implementation should create instances of the OrderShipper2 class, which itself has a dependency:

public class OrderShipper2 : IOrderShipper
{
    private readonly IChannel channel;
 
    public OrderShipper2(IChannel channel)
    {
        if (channel == null)
            throw new ArgumentNullException("channel");
 
        this.channel = channel;
    }
 
    public void Ship(Order order)
    {
        // Ship the order and
        // raise a domain event over this.channel
    }
}

In order to be able to create an instance of OrderShipper2, any factory implementation must be able to supply an IChannel instance.

Manually Coded Factory #

The first option is to manually wire up the OrderShipper2 instance within the factory:

public class ManualOrderShipperFactory :
    IOrderShipperFactory
{
    private readonly IChannel channel;
 
    public ManualOrderShipperFactory(IChannel channel)
    {
        if (channel == null)
            throw new ArgumentNullException("channel");
 
        this.channel = channel;
    }
 
    public IOrderShipper Create()
    {
        return new OrderShipper2(this.channel);
    }
}

This has the advantage that it's easy to understand. It can be unit tested and implemented in the same library that also contains OrderShipper2 itself. This means that any client of that library is supplied with a read-to-use implementation.

The disadvantage of this approach is that if/when the constructor of OrderShipper2 changes, the ManualOrderShipperFactory class must also be corrected. Pragmatically, this may not be a big deal, but one could successfully argue that this violates the Open/Closed Principle.

Container-based Factory #

Another option is to make the implementation a thin Adapter over a DI Container - in this example Castle Windsor:

public class ContainerFactory : IOrderShipperFactory
{
    private IWindsorContainer container;
 
    public ContainerFactory(IWindsorContainer container)
    {
        if (container == null)
            throw new ArgumentNullException("container");
 
        this.container = container;
    }
 
    public IOrderShipper Create()
    {
        return this.container.Resolve<IOrderShipper>();
    }
}

But wait! Isn't this an application of the Service Locator anti-pattern? Not if this class is part of the Composition Root.

If this implementation was placed in the same library as OrderShipper2 itself, it would mean that the library would have a hard dependency on the container. In such a case, it would certainly be a Service Locator.

However, when a Composition Root already references a container, it makes sense to place the ContainerFactory class there. This changes its role to the pure infrastructure component it really ought to be. This seems more SOLID, but the disadvantage is that there's no longer a ready-to-use implementation packaged together with the LazyOrderShipper2 class. All new clients must supply their own implementation.

Dynamic Proxy #

The third option is to basically reduce the principle behind the container-based factory to its core. Why bother writing even a thin Adapter if one can be automatically generated.

With Castle Windsor, the Typed Factory Facility makes this possible:

container.AddFacility<TypedFactoryFacility>();
container.Register(Component
    .For<IOrderShipperFactory>()
    .AsFactory());
var factory =
    container.Resolve<IOrderShipperFactory>();

There is no longer any code which implements IOrderShipperFactory. Instead, a class conceptually similar to the ContainerFactory class above is dynamically generated and emitted at runtime.

While the code never materializes, conceptually, such a dynamically emitted implementation is still part of the Composition Root.

This approach has the advantage that it's very DRY, but the disadvantages are similar to the container-based implementation above: there's no longer a ready-to-use implementation. There's also the additional disadvantage that out of the three alternative here outlined, the proxy-based implementation is the most difficult to understand.


Comments

So what is the advantage to having the manually-coded factory in this example at all? It violates the open/closed principle and provides a useless abstraction of the OrderShipper2 constructor. (Or did you just mention it because it is an example of what not to do?)
2012-03-16 00:35 UTC
Patrick, I just explained what the advantages (and disadvantages) are...
2012-03-16 04:47 UTC
Dmitriy #
Nice article, thanks.
But i have a question. What if object, created by factory, implements IDisposable? Where we should call Dispose()?

Sorry for my English...
2012-03-16 05:39 UTC
Good article, I hadn't considered the idea that a composition root can effectively span across factories. I guess it makes sense since most (all?) DI containers have a module system for binding, which is effectively a means of separating out the composition root.
2012-03-16 09:20 UTC
Dmitriy #
Sorry for offtopic. I have small bug report:
Often, when I open this blog from the google search results page, javascript function "highlightWord" hangs my Firefox. Probably too big cycle on DOM.
2012-03-16 10:30 UTC
About disposal, I can only think of two options - both of which are leaky abstractions: Either let the returned interface also implement IDisposable, or add a Release method to the Abstract Factory.

You can read more about this in chapter 6 in my book.

Regarding the bug report: thanks - I've noticed it too, but didn't know what to do about it...
2012-03-16 12:52 UTC
Thomas #
Mark

You have cleand up my doubts with this sentence "But wait! Isn’t this an application of the Service Locator anti-pattern? Not if this class is part of the Composition Root." I was not just confortable about if it's well done or not.

I use also Dynamic Proxy factory because it's a great feature.

Thomas
2012-03-16 14:22 UTC
Dmitriy #
I have read your book. :)
I thought about this "life time" problem. And I've got an idea.

What if we let a concrete factory to implement the IDisposable interface?
In factory.Create method we will push every resolved service into the HashSet.
In factory.Dispose method we will call container.Release method for each object in HashSet.
Then we register our factory with a short life time, like Transitional.
So the container will release services, created by factory, as soon as possible.

What do you think about it?

About bug in javascript ...
Now the DOM visitor method "highlightWord" called for each word. It is very slow. And empty words, which passed into visitor, caused the creation of many empty SPAN elements. It is much slower.
I allowed myself to rewrite your functions... Just replace it with the following code.

var googleSearchHighlight = function () {
if (!document.createElement) return;
ref = document.referrer;
if (ref.indexOf('?') == -1 || ref.indexOf('/') != -1) {
if (document.location.href.indexOf('PermaLink') != -1) {
if (ref.indexOf('SearchView.aspx') == -1) return;
}
else {
//Added by Scott Hanselman
ref = document.location.href;
if (ref.indexOf('?') == -1) return;
}
}

//get all words
var allWords = [];
qs = ref.substr(ref.indexOf('?') + 1);
qsa = qs.split('&');
for (i = 0; i < qsa.length; i++) {
qsip = qsa[i].split('=');
if (qsip.length == 1) continue;
if (qsip[0] == 'q' || qsip[0] == 'p') { // q= for Google, p= for Yahoo
words = decodeURIComponent(qsip[1].replace(/\+/g, ' ')).split(/\s+/);
for (w = 0; w < words.length; w++) {
var word = words[w];
if (word.length)
allWords.push(word);
}
}
}

//pass words into DOM visitor
if(allWords.length)
highlightWord(document.getElementsByTagName("body")[0], allWords);
}

var highlightWord = function (node, allWords) {
// Iterate into this nodes childNodes
if (node.hasChildNodes) {
var hi_cn;
for (hi_cn = 0; hi_cn < node.childNodes.length; hi_cn++) {
highlightWord(node.childNodes[hi_cn], allWords);
}
}

// And do this node itself
if (node.nodeType == 3) { // text node
//do words iteration
for (var w = 0; w < allWords.length; w++) {
var word = allWords[w];
if (!word.length)
continue;
tempNodeVal = node.nodeValue.toLowerCase();
tempWordVal = word.toLowerCase();
if (tempNodeVal.indexOf(tempWordVal) != -1) {
pn = node.parentNode;
if (pn && pn.className != "searchword") {
// word has not already been highlighted!
nv = node.nodeValue;
ni = tempNodeVal.indexOf(tempWordVal);
// Create a load of replacement nodes
before = document.createTextNode(nv.substr(0, ni));
docWordVal = nv.substr(ni, word.length);
after = document.createTextNode(nv.substr(ni + word.length));
hiwordtext = document.createTextNode(docWordVal);
hiword = document.createElement("span");
hiword.className = "searchword";
hiword.appendChild(hiwordtext);
pn.insertBefore(before, node);
pn.insertBefore(hiword, node);
pn.insertBefore(after, node);
pn.removeChild(node);
}
}
}
}
}
2012-03-16 16:26 UTC
Dmitriy #
Oops... formatting missed.

I upload .js file here http://rghost.ru/37057487
2012-03-16 17:08 UTC
Steve #
Does the manually coded factory really violate the OCP?

Granted, if the constructor to OrderShipper2 changes, you MUST modify the abstract factory. However, isn't modifying the constructor of OrderShipper2 itself a violation of the OCP? If you are adding new dependencies, you are probably making a significant change.

At that point, you would just create a new implementation of IOrderShipper.

2012-03-16 19:03 UTC
Good point, Steve. You're right... I hadn't thought it all the way through :)
2012-03-18 14:03 UTC
Dmitriy, if we let only the concrete factory implement IDisposable, then when should it be disposed? How can we deterministically signal that we are 'done' with it?

(Thank you very much for your assistance with the javascript - I didn't even know which particular script was causing all that trouble. Unfortunately, the script itself is compiled into the dasBlog engine which hosts this blog, so I can't change it. However, I think I managed to switch it off... Yet another reason to find myself a new blog platform...)
2012-03-18 18:25 UTC
Dmitriy #
I think we should have some sort of Scope to handle the life time ending. In request-based application it can be request. If we need smaller life time, we can write our own Scope, based on some application-specific events.

Btw, another thing I think about is the abstract factory's responsibility. If factory consumer can create service with the factory.Create method, maybe we should let it to destroy object with the factory.Destroy method too? Piece of the life time management moves from one place to another. Factory consumer takes responsibility for the life time (defines new scope). For example we have ControllerFactory in ASP.NET MVC. It has the Release method for this.
In other words, why not to add the Release method into the abstract factory?
2012-03-18 21:54 UTC
Implicit scopes like an HTTP request can work pretty well when we can hook into the lifetime cycle of the scope itself. This is possible with HTTP requests, which is why many DI Containers can implicitly clean up when the HTTP request has been handled.

However, what if we have a desktop application or a long-running batch job? How do we define an implicit scope then? One option might me to employ a timeout, but I'll have to think more about this... Not a bad idea, though :)
2012-03-19 10:42 UTC
In multithreaded applications we can use a Thread as a smallest scope.
But for a single long-lived thread we have to invent something.

It seems that there is no silver bullet in the management of a lifetime. At least without using Resolve-Release pattern in several places instead of one ...

Can you write another book on this subject? :)
2012-03-19 12:02 UTC
Dmitriy, I still need to think more about this, but AFACT in order to use a scope for decommissioning, there must be some hook that we can attach to in order to clean up when the scope ends. I'm not aware of such a hook on a Thread, but I must admit that I rarely do low-level work with Threads.

A Task<T>, on the other, provides us with the ability to attach a continuation, so that seems to me to be an appropriate candidate...
2012-03-24 08:46 UTC
Hennadii Omelchenko #
Mark, how does Container-Based factory put up with Register-Resolve-Release pattern? For instance, if we have ten different factories, then we end up with at least ten 'Resolve' calls, and you state in your book that there must be only one, in composition root
2012-12-23 14:31 UTC
You could create each factory instance using the "new" keyword and register the instances with the container.

Or you could register the container with itself, enabling it to auto-wire itself.

None of these options are particularly nice, which is why I instead tend to prefer one of the other options described above.
2012-12-23 15:02 UTC
Julien Vulliet #
Interesting article, one thing I'm wondering (apart from many other questions which would likely require a post or two on their own as an answer), isn't finally using the dynamic proxy solution somehow a hidden dependency to your container? You don't have explicit reference, but if you swap container you might have an issue with this being implemented differently (one container might prefer func, another one interfaces....), so finally you're not able to swap container that easily?
2014-02-28 22:58 UTC

Julien, thank you for your question. Using a Dynamic Proxy is an implementation detail. The consumer (in this case LazyOrderShipper2) depends only on IOrderShipperFactory.

Does using a Dynamic Proxy make it harder to swap containers? Yes, it does, because I'm only aware of one .NET DI Container that has this capability (although it's a couple of years ago since I last surveyed the .NET DI Container landscape). Therefore, if you start out with Castle Windsor, and then later on decide to exchange it for another DI Container, you would have to supply a manually coded implementation of IOrderShipperFactory. You could choose to implement either a Manually Coded Factory, or a Container-based Factory, as described in this article. It's rather trivial to do, so I would hardly call it blocking issue.

The more you rely on specific features of a particular DI Container, the more work you'll have to perform to migrate. This is why I always recommend that you design your classes following normal, good design practices first, without any regard to how you'd use them with any particular DI Container. Only when you've designed your API should you figure out how to compose it with a DI Container (if at all).

2014-03-01 14:47 UTC
jam40jeff #
Isn't the first option (manually coded factory carrying instance dependencies as factory dependencies) the only one which still allows for complete container verification? If that is the case, wouldn't that alone trump any other reasons not to use this option?
2014-12-31 20:57 UTC

Personally, I don't find container verification particularly valuable, but then again, I mostly use Pure DI anyway.

2014-12-31 21:33 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or somewhere else with a permalink. Ping me with the link, and I may respond.

Published

Thursday, 15 March 2012 21:01:13 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!
Published: Thursday, 15 March 2012 21:01:13 UTC