Pattern Recognition: Abstract Factory or Service Locator? by Mark Seemann
It's easy to confuse the Abstract Factory pattern with the Service Locator anti-pattern - particularly so when generics or contextual information is involved. However, it's really easy to distinguish between there two, and here's how!
Here are both (anti-)patterns in condensed form opposite each other:
Abstract Factory | Service Locator |
public interface IFactory<T> |
public interface IServiceLocator |
For these examples I chose to demonstrate both as generic interfaces that take some kind of contextual information (context) as input.
In this example the context can be any object, but we could also have considered a more strongly typed context parameter. Other variations include more than one method parameter, or, in the degenerate case, no parameters at all.
Both interfaces have a simple Create method that returns the generic type T, so it's easy to confuse the two. However, even for generic types, it's easy to tell one from the other:
An Abstract Factory is a generic type, and the return type of the Create method is determined by the type of the factory itself. In other words, a constructed type can only return instances of a single type.
A Service Locator, on the other hand, is a non-generic interface with a generic method. The Create method of a single Service Locator can return instances of an infinite number of types.
Even simpler:
An Abstract Factory is a generic type with a non-generic Create method; a Service Locator is a non-generic type with a generic Create method.
The name of the method, the number of parameters, and other circumstances may vary. The types may not be generic, or may be base classes instead of interfaces, but at the heart of it, the question is whether you can ask for an arbitrary type from the service, or only a single, static type.
Comments
1) i've always viewed an IoC container (whether it's used for dependency injection or service location) as an amalgamation of design pattern, including the abstract factory (along with builders, registries, and others)
2) a design pattern is not always identified by implementation detail, but by intent. take a look at the Decorator and Proxy design patterns as implemented in C#, for example. There are, quite often and in the most basic of implementations, very few differences between these two patterns when it comes down to the implementation. the real difference is the intent of use
i don't think you are necessarily wrong in what you've said. i do think there's much more room for a gray area in between these two patterns, though. a service locator is an abstract factory (along with many other things), and an abstract factory can be used as a service locator. so, while the two patterns are distinct in their intent, they are often blurred and indistinguishable in implementation.
However, the whole point is that there are fundamental differences between Abstract Factory and Service Locator. One is good, the other is evil. Learning to tell them apart is important.
is it? looks to me like the Create method IS generic, it just so happens to have a constraint