Design Patterns VS Design Principles: Factory method
Let’s examine another design pattern in our “Design Patterns VS Design Principles” series, where we relate design patterns to design principles. Today, we focus on the Factory method design pattern.
We’ll see the various forms the Factory method design pattern can take, the differences with the Abstract Factory method, and to which design principle the Factory method pattern relates to.
Design patterns and design principles
In case you’re just joining the series, let’s see what we call a design pattern and a design principle.
A design pattern is one of the patterns presented in the classic Gang of Four (GoF) book Design Patterns:
Design principles, on the other hand are more general guidelines to make design robust. The GRASP principles are 9 principles to assign responsibilities to components in code, and they are presented in Craig Larman’s Applying UML and Patterns book:
The 9 GRASP design principles are:
- Low Coupling
- High cohesion
- Creator
- Information expert
- Polymorphism
- Indirection
- Protected Variations
- Pure Fabrication
- Controller
Let’s analyse the GoF design pattern Factory method, and find out to which GRASP principle it relates most.
Factory method
To understand what factory method means, let’s analyse each of its two words:
- method: this means member function,
- factory: this means something that creates objects.
All this means that a factory method is a member function that creates objects.
It is important to note that this comes from a book on object oriented design (the GoF’s Design Patterns book) , that makes heavy use of member functions. But my understanding of the design pattern is that it applies beyond member functions. It applies to free functions too.
So a more generic and idiomatic name for this design pattern in C++ could be “Factory function”.
Factory member functions
The GoF book illustrates the Factory method pattern with a polymorphic member function that returns a polymorphic object. The example is (in essence and in more modern) something like this:
class X { /* ... */ }; class SomeTypeOfX : public X { /* ... */ }; class MyClass { public: // interface of MyClass... virtual std::unique_ptr<X> createX() const; }; class MyDerivedClass : public MyClass { public: std::unique_ptr<X> createX() const override { return std::make_unique<SomeTypeOfX>(); } };
The Factory method here is createX
. Its only role is to create an X
(or an object behaving like an X
) and it is the only place in the code that creates an X
.
This example uses polymorphism in two places: the factory method is polymorphic, and the created object is polymorphic too. But I don’t think those are essential conditions for the design pattern. A non-polymorphic method could just as well be in charge of creating a non-polymorphic object too.
For this reason, I don’t think that Factory method, in its essence, relates to the Polymorphism design principle. Rather, I would relate it to Pure Fabrication. Indeed, it is convenient for cohesion to centralise the responsibility of creating an object in one member function, even if this function doesn’t represent an element of the domain of the application.
Factory free functions
To illustrate how Factory method can also be implemented with a free function, let’s see the common pattern of the factory function. Before learning design patterns, this is what I thought the generic name “factory” referred too.
Consider the case where we have a class hierarchy:
class Base { /* ... */ }; class Derived1 : public Base { /* ... */ }; class Derived2 : public Base { /* ... */ }; class Derived3 : public Base { /* ... */ };
And we only know at runtime the type of the object we need to create. This information is represented by an enum:
enum class Type { Type1, Type2, Type3 };
(those are names to illustrate the concepts, in production code we wouldn’t use such names with no information!)
To create an object of the appropriate type, and let the rest of the code use it polymorphically through the Base
interface, we can centralise the creation in one function:
std::unique_ptr<Base> createObject(Type type) { switch (type) { case Type::Type1 : return std::make_unique<Derived1>(); case Type::Type2 : return std::make_unique<Derived2>(); case Type::Type3 : default: return std::make_unique<Derived3>(); } };
This falls under the Factory method design pattern too. And I would also relate this form to the Pure Fabrication principle, as it is a convenient way to centralise the responsibility of creating the object even if it doesn’t mirror a domain concept.
Why not Creator?
It would have sounded nice to relate the Factory method design pattern to the Creator design principle. Indeed, the sole role of the Factory method pattern is to create object (we saw that it didn’t relate to the Polymorphism principle).
However, the Creator principle is something else: it suggests that B should create A if B is going to interact with A, has input to create A, or is, more generally, close to A.
The Factory method is not close to the object it creates, in my view. Once it created it, the factory doesn’t necessarily continue to interact with the object.
The differences between Abstract Factory and Factory method
Abstract Factory and Factory method are two design patterns with the name “factory” in it, and they both describe patterns to create objects. The classical question is then: what is the difference between them?
I won’t describe how Abstract Factory works because it is a topic in itself and it is out of the scope of this article (it you’re not sure about how Abstract Factory works, check out the article dedicated to Abstract Factory).
Here are the differences I see between the two patterns:
- Abstract Factory creates several objects of the same family or brand, whereas Factory method only creates one.
- The essence of Abstract Factory is to provide Polymorphism in the creation of objects, whereas Factory method is only a Pure Fabrication to centralise the creation of an object.
Do you see other differences between the two patterns?
Do you agree with the attribution of Factory method to Pure Fabrication?
Do you often use design patterns and design principles in your code?
Leave a comment below.
You will also like
- Design Patterns VS Design Principles: Abstract Factory
- Minor, Major and Overarching Design Principles
- GRASP: 9 Must-Know Design Principles for Code
- Design Patterns VS Design Principles: Iterator, Mediator and Memento
- Design Patterns VS Design Principles: Template Method
Share this post!