State Design Pattern
Classic GOF Behavioral Design Patterns
Intent
The Abstract Factory is a creational design pattern that lets you produce families of related objects without specifying their concrete classes. Abstract Factory patterns work around a super-factory which creates other factories. This factory is also called as factory of factories.
Typically, in the Abstract Factory pattern an interface is responsible for creating a factory of related objects without explicitly specifying their classes. Each generated factory can give the objects as per the Factory pattern.
The Abstract Factory pattern is pretty common in code.
It is used when:
- There is a need to provide an interface for creating families of related or dependent objects without specifying their concrete classes.
- There is a hierarchy that encapsulates: many possible object types, and their needs to be a facility to create them easily.
- The new operator considered harmful.
Problem
Many frameworks and libraries use it to provide a way to extend and customize their standard components.
The pattern is easy to recognize by methods, which return a factory object. Then, the factory is used for creating specific sub-components as desired.
Discussion
The Abstract Factory pattern is used to provide a level of indirection that abstracts the creation of families of related or dependent objects without directly specifying their concrete classes. Typically, a "factory" object has the responsibility for providing creation services for the entire object family. Clients never have to create objects directly, they ask the factory to do that on their behalf.
This appraoch to creating objects makes exchanging entire object families easy because the specific class of the factory object appears only once in the application - where it is instantiated. This allows the application to perform wholesale replacement of the entire family of objects simply by instantiating a different concrete instance of the abstract factory.
Because the service provided by the factory object is so pervasive, it is routinely implemented as a Singleton.
Structure
The Abstract Factory is an extremely common pattern, in fact, it enables architectures such as Dependency Injection.
Unfortunately, it's also one of the patterns that's prone to overuse: it's easy to start using Abstract Factories anytime you need to create objects. Be aware of when you decide to use this pattern, and make sure you actually need it.
While it seems like there is a lot going on the the diagram above, it's actually very straight-forward to understand. The AbstractFactory defines the interface (where supported) which all of the concrete factories will need to implement in order to create Items. ConcreteFactoryOne and ConcreteFactoryTwo have both implemented this interface here, creating two seperate families of items. Meanwhile, AbstractItemA and AbstractItemB are interfaces for the different types of items to be created. Each factory will create one of each of these AbstractItems.
The Client deals with AbstractFactory, AbstractItemA and AbstractItemB. The Client doesn't know anything about the implementations or even how they are instantiated. The actual implementation of AbstractFactory that the Client uses is determined at runtime.
As you can see, one of the main benefits of this pattern is that the client is totally decoupled from the concrete products. Also, new item families can be easily added into the system, by just adding in a new type of ConcreteFactory that implements AbstractFactory, and creating the specific Product implementations.
Practical Example
A sample scenario that we will discuss using the Abstract Factory pattern uses employees and consultants. Imagine a large company that has different process for bringing consultants and employees into the organization based on whether they work at the corporate headquarters or at another satellite location. Employees and Vendors are used throughout the organization regardless of location, but the processes for adding/creating them is different.
This diagram should appear very similar to the generic diagram in STRUCTURE above. In this specific case, the AbstractItemA and AbstractItemB interfaces have been replaced with AbstractEmployee and AbstractConsultant respectively. The ConcreteFactories have been exchanged for factories that are specific to the type of process used to acquire the person - here there is a PreferredFactory and a StandardFactory.
Let's continue this sample with some practical code below.
Code Samples
Below, you will find examples of the Abstract Factory implemented in four different commonly used languages. Each one of the examples implements the exact same scenario as described in the PRACTICAL EXAMPLE section above.
Each sample will use abstact factories to return proper instances.
C# Abstract Factory Code Sample
In this C# example, the Abstract Factory pattern is used to create two different families of employee and consultants.
The abstract definitions are created here using interfaces, although an abstract class could have been used as well. The AbstactEmployee and AbstractConsultant interfaces are required beacuse they are the only types known by the client (other than the AbstractFactory). They are also required because we still need to ensure that employee and consultant types have the same definiton (properties and methods) regardless of which factory is used to create them - done by implementing the interface on all child classes.
Two different employee and consultant types are created.
Java Abstract Factory Code Sample
In this java example, the Abstract Factory pattern is used to create two different families of employee and consultants - one standard and one preferred.
The abstract definitions are created here using abstract classes, although an interface could have been used as well. The AbstactEmployee and AbstractConsultant classes are required beacuse they are the only types known by the client (other than the AbstractFactory). They are also required because we still need to ensure that employee and consultant types have the same definiton (properties and methods) regardless of which factory is used to create them - done by extending them in child classes.
Two different employee and consultant types are created.
Typescript Abstract Factory Code Sample
In this example, the Abstract Factory pattern is used to create two different families of employee and consultants.
The abstract definitions are created here using interfaces. The AbstactEmployee and AbstractConsultant interfaces are required beacuse they are the only types known by the client (other than the AbstractFactory). They are also required because we still need to ensure that employee and consultant types have the same definiton (properties and methods) regardless of which factory is used to create them - done by implementing the interface on all child classes.
Two different employee and consultant types are created.
JavaScript Abstract Factory Code Sample
JavaScript does not support class-based inheritance therefore the abstract classes as depicted in the diagram are not used in the JavaScript sample. Abstract classes and interfaces enforce consistent interfaces in derived classes. In JavaScript we must ensure this consistency ourselves by making sure that each 'Concrete' object has the same interface definition (i.e. properties and methods) as the others
In the example we have two Concrete Factories: StandardFactory and PreferredFactory. The first one creates Standard instances, the second one Preferred instances. Both objects are person types (with the same interface) which allows the client to treat them the same. An array with two employees and two consultants is created. Each person is then asked to say what and who they are.
The log function is just a helper which collects and displays results.
Considerations
- Decide if independence of creation services are the current source of pain.
- Map out a matrix of the hierarchy of "items".
- Define a factory interface that consists of a factory method per item.
- Define a factory derived class for each heirarchy branch that encapsulates all references to the new operator.
- The client should retire all references to new, and use the factory methods to create the various objects
Additional Notes
- Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementary: Abstract Factory might store a set of Prototypes from which to clone and return product objects, Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
- Abstract Factory, Builder, and Prototype define a factory object that's responsible for knowing and creating the class of product objects, and make it a parameter of the system. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object (aka prototype) building a product by copying a prototype object.
- Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype.
- Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
- Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
- Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.