The Abstract Factory pattern defines an interface for creating families of related/dependent objects without needing to specify concrete classes. It supports the Open closed principle. The Abstract Factory pattern is a way of defining a family of related Factory Methods.
- A system needs to be independent of how its objects are created, composed and represented.
- There are several different families of objects that a system may be configured with.
- You want to enforce that a family of objects need to be used together.
- You want to provide a class library of objects and only reveal their abstract interfaces, not the concrete implementations.
AbstractFactory: Declares an interface for creating abstract product objects. ConcreteFactory: Implements the create() methods for a specific family of related objects. AbstractProduct: Declares an interface for a type of product object. ConcreteProduct: Defines a product object that is created by the corresponding concrete factory. Client: Uses only the abstract interfaces.
This example from the Gang of Four book shows an interface that supports two types of "look-and-feels" - Motif and Presentation Manager. These have different appearances and behaviours for interface Widgets such as Windows and ScrollBars. In order for the Widgets to be reusable, they should not be hard-coded to a specific look and feel. The look and feel needs to be able to be changed dynamically during runtime, and there should only ever be one type of look and feel widgets displayed at a time.
The WidgetFactory is the solution, it declares an interface for creating each type of Widget. WidgetFactory returns a new Widget object for each abstract Widget class. There is a concrete WidgetFactory for each type of look and feel, which implement the abstract create() methods to create the corresponding type of Widget. Clients call the abstract create() methods to get a Widget instance. Clients only deal with the abstract classes instead of the concrete implementations, which is good design. They are independent of whatever look and feel is being used.
Java Code Example: you can find a nicely explained java code example of the Abstract Factory Pattern here
- The factory encapsulates the process and responsibility of creating product objects. This isolates the clients from the concrete implementations.
- As a direct outcome of first consequence, Abstract Factory successfully fulfils Keep related data and behavior in one place and Program to the interface not the implementation principles of OO design.
- Product families can be exchanged easily. In the example above, Motif widgets can be switched to Presentation Manager widgets by simply switching the corresponding factory objects and redrawing the interface.
- Enforces the constraint that families of objects need to be used together, and that the application can only use objects from one family at a time.
- It is hard to add new kinds of products by extending an Abstract Factory, because the Abstract Factory interface fixes the set of possible products it creates. All subclasses of Abstract Factory will need to be changed. So does this violate the Open closed principle ??? The changes to Concrete Factory would consist of adding the new methods for creating newly added products. This would mean that we are not changing existing code but only adding new parts and the old code is still intact and doesn't need to be re-tested. This suggests that Open closed principle is not violated.
Related Design Patterns
- Singleton: Generally only one ConcreteFactory is required per family of objects, so the Singleton pattern can be used for them.
- Factory Method: A Factory Method can be used to create each Concrete Product. The Concrete Factory specifies its Products by overriding the factory method for each Product. This requires a new Concrete Factory subclass for each Product family.
- Prototype: If there are many Product families, an alternate solution is to use the Prototype pattern, which eliminates the need for a new Concrete Factory class for each product family. The Concrete Factory is initialised with a Prototype instance of each product in the family, and creates new products by cloning the Prototype.
Recognising the pattern
Classes: AbstractFactory, multiple Factories, multiple Products
- abstract AbstractFactory class
- AbstractFactory contains abstract createProduct() methods that return a Product
- multiple Factory classes that override createProduct() methods
- multiple Product interfaces
Creational: Abstract Factory | Builder | Factory Method | Prototype | Singleton