3

I am seeking clarification on the exact purpose and definition of the Abstract Factory pattern.

According to the GoF (Gang of Four) book, the intent of the pattern is to:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

In the applicability section, it is recommended to use this pattern when:

  • A system should be configured with one of multiple families of products.
  • A family of related product objects is designed to be used together, and you need to enforce this constraint.

From this, it seems that the pattern is about isolating the client from the concrete implementation of a family of classes, ensuring that certain objects are used together as a family. For example:

public interface GuiAbstractFactory
{
    IButton GetButton();
    ITextBox GetTextBox();
}

However, I am confused because I have seen the term "Abstract Factory" used to refer to classes that expose a creation method for a single product, rather than a family of products. For example:

public interface ILoggerFactory
{
    ILogger GetLogger(string name);
}

In particular, I have encountered blog posts and books that describe this usage:

Blog post by Mark Seemann

Blog post by Steven van Deursen's

Seemann, M., & Van Deursen, S. (2019a). Dependency injection principles, practices, and patterns

Can someone clarify whether using the term "Abstract Factory" to refer to factories creating single products is correct? How does this usage align or conflict with the original GoF definition?

1
  • 2
    The family of one is a family. Why is this a problem?
    – Basilevs
    Commented Jun 16 at 10:31

1 Answer 1

5

In short

It's just an ambiguity in the human language.

More arguments

Factory methods can be abstract

The pattern where a factory creates a single product is the GoF's Factory Method pattern, which matches the design of ILoggerFactory:

Define an interface for creating an object, but lets the subclass decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

The main issue with this pattern is its ambiguous naming, which suggests it's about a method, whereas in reality it's about a factory. So people often use the shortcut "Factory". And in modern programming languages, the factory is in general defined as an interface, so an abstraction without implementation. This makes the "Factory", technically speaking, an "abstract factory" in the OOP meaning, not in the GoF meaning. So the use of this terminology is perfectly valid.

Abstract factories could be about a single product

Let's look at the intent of abstract factories with a slightly different emphasis:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Here it's about decoupling the creation of abstract objects from their concrete implementation. Interestingly, everything in this design is about abstracting products to be created, and hence abstracting their creation. Unlike the factory method, where the factory can delegate the choice of the product to a subclass or implement a default choice (i.e. use a concrete product rather than an abstract one), the abstract factory must delegate the creation of the products to a concrete factory (since it is not possible to instantiate abstract products).

Nothing in the design of this pattern requires more than one abstract product. The only ambiguity is the use of the term "families of related objects", which is not technically well defined and may suggest that it is more than one. But if the more neutral term of "group" or "set" would be used instead, nobody would argue about the validity to have only one abstract product in the "group"/"set" with only one member.

With this interpretation, the ILoggerFactory would also match the definition of an abstract factory, this time from a GoF point of view.

Some more arguments about GoF context

The GoF did not require the factory method TO BE an interface but TO DEFINE an interface. The GoF allows for example the Factory Method to be defined as a class that propose a default implementation (which is possible only if the product is itself not abstract). GoF also proposes implementation variants that avoid using abstract methods completely. Last but not least GoF also mentions implementation where the product class embeds a factory method. So some of the proposed approach of the factory pattern differ more substantially from the GoF's abstract factory.

But in the context of DI, the Factory Method is always an interface and hence eligible for being called "abstract factory" and there is an overlap with the abstract factory pattern.

Also, GoF aims to provide solution for common problems. And the possibility of having several families of related products that interact between them and require some compatibility is quite common. Not mentioning families in plural in the abstract factory would have missed this specific use case.

3
  • 2
    The term "family" in technical contexts (like math) typically just means "a set of objects that are somehow related or of the same kind". E.g., f(x) + C is a family of functions that have the same shape as f(x) but differ in value by some constant C. GoF used it with a meaning that was something like: a set of derived types designed to work together. The Abstract Factory then provides a way to dynamically create their instances when needed, without mixing together types from different families (that are not designed or guaranteed to cooperate nicely). Commented Jun 16 at 3:24
  • @FilipMilovanović, that was always my interpretation of the GoF abstract factory pattern as well. There was an implied cohesiveness between the concrete types generated by the abstract factory, which simplified object construction to make sure these things worked well together. The assumption was if you use a non-compatible concrete type then the whole cluster of objects would behave incorrectly or unpredictably. Commented Jun 16 at 15:36
  • @FilipMilovanović thanks for the additional thoughts. In view of this argument, I've reformulated to be more blunt on this aspect.
    – Christophe
    Commented Jun 17 at 5:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.