Card 01/ 08

ConceptDifficulty: Intermediate3 min

Abstract Factory Pattern: Creating Families of Objects That Belong Together

One object makes every product a family needs, so you cannot mix a Windows button with a Mac menu.

The Abstract Factory pattern provides one interface for creating a whole family of related objects, with one implementation of that interface for each family. Code that needs the objects asks the factory for each one and never names a concrete class, so it gets a matching set every time. This card covers the problem of mismatched objects, the intent, and when the pattern is worth its classes.

The problem appears when several objects must come from the same family. An application that stores receipts in a bucket and announces them on a queue must use AWS's bucket with AWS's queue, or Google Cloud's with Google Cloud's. If each object is created separately, wherever it is needed, nothing stops one line from creating an S3 bucket and another a Pub/Sub topic, and the mistake shows up only when the program runs.

Creating related objects separately and through one factory

Without the patterneach object chosen on its own line

py
def archive_order(order_id, receipt):
    storage = S3Storage()
    queue = PubSubQueue()
    storage.put(f"receipts/{order_id}.txt", receipt)
    queue.publish(f"order-archived {order_id}")

This pairs an AWS bucket with a Google Cloud queue, and nothing in the code says they disagree.

With the patternone factory decides the family

py
def archive_order(cloud: CloudFactory, order_id, receipt):
    storage = cloud.create_storage()
    queue = cloud.create_queue()
    storage.put(f"receipts/{order_id}.txt", receipt)
    queue.publish(f"order-archived {order_id}")

Pass AwsFactory() and both are AWS. Switching provider is one argument.

The Gang of Four state the intent as: provide an interface for creating families of related or dependent objects without specifying their concrete classes. The interface is the abstract factory, with one creation method for each kind of product, and each family is a concrete factory.

Think of a furniture range. Buy from the Victorian range, and the chair, the sofa and the table all match. The analogy breaks in one place: a shop will happily sell you a Victorian chair and a modern table, while an abstract factory makes mixing impossible, because each factory only ever returns its own family.

Abstract Factory is one of five creational patterns, the family that controls how objects are created.

The creational family, with this pattern marked
PatternWhat it decides
Factory MethodWhich class a subclass creates, through one overridable method.
Abstract Factory (this topic)Which family of related classes is created, through one object.
BuilderHow a complex object is put together step by step.
PrototypeWhich existing object a new one is copied from.
SingletonThat a class has only one instance.
Abstract Factory

Use it when

  • Several kinds of object must always come from the same family, such as one provider, one theme or one database vendor.
  • The whole family should be chosen in one place, often at start-up, and switched without editing the code that uses it.
  • New families are expected more often than new kinds of product.

Avoid it when

  • There is only one kind of product, which makes it Factory Method or a plain parameter.
  • There is only one family and no second in sight.
  • New kinds of product are added often, since each one edits every factory.