Factory pattern: the key information on the factory method pattern
More than 500,000 copies of ‘Design Patterns: Elements of Reusable Object-Oriented Software’ have been sold since its release in 1994. The book for software developers describes 23 different design patterns, also known in professional circles as ‘Gang of Four’ design patterns – a term that goes back to the four authors Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm.
Among the many design strategies taught in this publication is the so-called factory method, which allows a class to delegate the creation of objects to subclasses. Concrete information on how to use this practical method is provided in particular by the factory method pattern, which is often today simply referred to as the factory pattern.
What is the factory pattern (factory method pattern)?
The SOLID principles are a subset of the principles of object-oriented design, which are intended to improve the development process of object-oriented software. The acronym “SOLID” stands for the following five principles:
- Single responsibility principle: Each class should have only one responsibility.
- Open-closed-principle: Software units should be expandable without having to change their behavior.
- Liskov substitution principle: A derived class should always be used instead of its base class.
- Interface segregation principle: Interfaces should be perfectly adapted to the requirements of the accessing clients.
- Dependency inversion principle: Classes on a higher level of abstraction should never depend on classes on a lower level of abstraction.
Instead of the usual description, the abbreviated term “factory pattern” or “factory method design pattern” is used in many cases, although it’s nowhere to be found in the GoF. If you look into the book, you’ll find that – besides the factory method pattern discussed here – only the similar abstract factory pattern exists, which defines an interface for the creation of a family of objects whose concrete classes are only defined during runtime.
What is the goal of the factory method pattern?
The factory pattern aims to solve a fundamental problem in instantiation – i.e., the creation of a concrete object of a class – in object-oriented programming. In principle, creating an object directly within the class that needs or should use this object is possible, but very inflexible. It binds the class to this object and makes it impossible to change the instantiation independently of the class. This kind of code is avoided in the factory pattern approach by first defining a separate operation for creating the object – the factory method. As soon as this is called up, it generates the object instead of the class constructor already mentioned.
Factory pattern: UML diagram of the factory method pattern
In software that is based on the factory method design pattern, the code of an object to be created (in this context also referred to as the ‘product’) is outsourced into a separate class. This abstract class, also called the ‘creator’ or – matching the pattern – ‘factory’, delegates the object instantiation to a subclass (ConcreteCreator), which ultimately decides which product is created. For this purpose, the ConcreteCreator takes over the method createProduct() and returns a ConcreteProduct, which can optionally be extended by the Creator with production code before it is passed to the interface as a finished product.
The process is made clear in the below UML class diagram of the factory pattern, which graphically summarises the relationships and processes described.
The pros and cons of the factory method design pattern
In the factory pattern, calling a programming method is completely separated from the implementation of new classes, which comes with its advantages. For example, this condition has a particular effect on how software can be extended: Factory methods have a high degree of autonomy which means they let you add new classes without the application having to change in any way – in parallel to runtime. In doing so, it’s sufficient to implement the factory interface and incorporate the creator accordingly (via ConcreteCreator).
Another advantage is the straightforward testability of the factory components. For example, if a Creator implements three classes, their functionality can be tested individually and independently of the class that’s being called out. In the case of the latter, it is only necessary to ensure that it calls out the creator properly, even if the software is extended at a later point in time. A further advantage is the possibility to give factory methods (unlike a class constructor) a meaningful name.
The biggest weakness of the factory design pattern is the fact that its implementation leads to a strong increase in the number of integrated classes, because every ConcreteProduct always requires a ConcreteCreator. As profitable as the factory approach is in principle regarding the extension of software, it is also disadvantageous when it comes to the effort required: If a product family is to be extended, not only the interface but all subordinate ConcreteCreator classes have to be adapted accordingly. Solid planning in advance regarding the required product types is therefore indispensable.
Advantages | Disadvantages |
---|---|
Modular expandability of the application | High number of required classes |
Good testability | Extension of the application is very elaborate |
Significant method names |
Where is the factory method pattern used?
The factory pattern can prove valuable in various application scenarios. Software where the concrete products to be created are unknown or are not defined in advance benefits from the alternative approach for subclass management. Typical use cases include frameworks or class libraries, which have become virtually indispensable as a basic framework for the development of modern applications.
Authentication systems also benefit from the advantages of the factory design pattern: Instead of a central class with various parameters that vary according to user authorisation, the authentication process can be delegated to factory classes that make independent decisions about the handling of the respective user.
In addition, the design according to the factory pattern approach is generally suitable for all software in which new classes are added regularly and according to plan – especially if these classes have to go through the same creation process.
Factory pattern: example (PHP)
The factory method design pattern can be used in various applications in different programming languages. Some of the best-known representatives include Java, JavaScript, C++, C#, Python, and PHP. The latter scripting language is also used in the following practical example, which is inspired by a German blog post by Phpmonkeys.
In this case, a scenario with the abstract class ‘Car’ (Creator) and the factory class ‘CarFactory’ (ConcreteCreator) is set. The former is designed as simple as possible and contains only code to set a colour for the car – default colour: white – and to read it out:
class Car {
private $color = null;
public function __construct() {
$this->color = "white";
}
public function setColor($color) {
$this->color = $color;
}
public function getColor() {
return $this->color;
}
}
In the factory class, methods for ‘red’ and ‘blue’ cars and a private method for the actual class creation are introduced:
class CarFactory {
private function __construct() {
}
public static function getBlueCar() {
return self::getCar("blue");
}
public static function getRedCar() {
return self::getCar("red");
}
private static function getCar($color) {
$car = new Car();
$car->setColor($color);
return $car;
}
}
Thanks to the factory method pattern, this clearly arranged factory method can now be extended with a wide variety of additional features such as additional colours, the brand of the car, or its price.