Tuesday 1 November 2011

Comment on Mark Seemann’s post on Abstract Factory and Service Locator

Mark Seemann has a post that I’ve been puzzling over, because the patterns he presents didn’t make sense to me. It’s about a year old, but the issues seem to come up again and again. I thought I’d hash over it for my own benefit.

He’s summarizing the differences between Abstract Factory and Service Locator, saying they’re easily confused but are actually easy to differentiate.

He shows a condensed Abstract Factory interface:

public interface IFactory<T>
{
    T Create(object context);
}

and states that Abstract Factory is a generic type that can only return instances of one type -- the type given by the generic parameter.

To me that’s not an Abstract Factory. The original Design Patterns book states that the pattern’s intent is creating families of related or dependent objects; it can therefore a single factory type can create instances of multiple types. Mark’s factory can only create one type, dictated by the closed type of the factory.

A real abstract factory interface might looks more like:

public interface IEcosystem
{
    IHumanoid CreateHumanoid();

    ICreature CreateCreature();
}

This does look a little like a Service Locator, in that it each IEcosystem-derived type can return multiple types. A Service Locator also doesn’t need to be generic – it might have a distinct method per service type returned.

He also posits a simplified ServiceLocator interface:

public interface IServiceLocator
{
    T Create<T>(object context);
}

(again, slightly condensed by me) that has a method named Create. Again, this interface doesn’t look right. A Service Locator doesn't handle instantiation for you, it simply hands you references to single already-instantiated services; it's a structural pattern. I'd have expected a method like T Locate<T>(object context).

Specific instances of Service Locator might be created -- if you relax the requirement that it's a singleton -- that are then populated with distinct sets of services for different domains, but typically you wouldn't need multiple Service Locator types.

For me the key difference between Abstract Factory and Service Locator is that the first is a creational pattern, and the second a structural pattern.

The Factory exists in single instances of multiple distinct types, one for each family of related classes. The Locator is traditionally a singleton at global scope, with which single instances of each type supported are registered; it also supports types that are contextually related but not necessarily as closely related as those supported by the Factory.

No comments: