Design Patterns — A quick guide to Abstract Factory.

Andreas Poyias
6 min readDec 10, 2018

--

This is a quick-guide to mastering one of the most commonly used design patterns, the Abstract Factory. Even though the coding examples will be in C++ as I am more comfortable with, they can be easily adjusted to any programming language like Java, Python, C#, Javascript and more.

Abstract Factory is classified in the creational design patterns which is all about class/object instantiation. More precisely, how to effectively use inheritance (class-creation patterns) or delegation (object-creation patterns). [by Design Patterns explained simply]

Factory definition: “It is a building or group of buildings where products are manufactured/created”. Products are then being sent to the clients for use at their own responsibility. At the same time, the factory clients are many, it should be fairly easy for the clients to order their product and similarly easy for the factory to adapt according to the client’s needs.

Let’s connect the dots to understanding this design pattern. We use it when we need an interface for the creation of dependent objects without necessarily specifying their concrete classes. At the same time, we want to encapsulate the construction of “products” using inheritance.

Step 1 — Keywords

Defining keywords is the secret recipe in this series of quick-guides. This method helped me truly understand the design patterns, hardcode them in my mind and comprehend the differences among other design patterns.

  1. Product: It is an object built by a factory and it is included in a family of objects. It is very specific as there is no abstraction to it. Example: BMWdoorHandle, FordDoorHandle.
  2. Abstract Product: It is a higher level view of a product which defines its family. Example DoorHandle, DoorWindow
  3. Concrete Factory: It is a factory that is “physically” micro-managing the creation and completion of a product. Example: BMWFactory, FordFactory.
  4. Abstract Factory: Is an interface for creating families of related or dependent objects without specifying their concrete classes. Example: CarFactory

Step 2 —Diagram

When discussing Abstract Factory everything should be relevant to the keywords above. If the code starts to diverge from those words then probably something isn’t quite right. Let’s make this simple, Concrete Factory is inheriting from Abstract Factory and Product from Abstract Product. The diagram is as plain as it looks; two classes inheriting from their abstract classes. The concrete factory is the one to do the dirty work to create specific Products (which is identified by the red line). Now with this diagram, it is easy to understand that this design pattern can easily be updated by adding more concrete factories and more products i.e. ProductC, ProductD etc. In other words, this picture can only grow wider and definitely not in height.

Step 3 — Code by example

I would suggest to copy the code class by class from my git repository “Andreas Poyias” and paste it in any online C++ editor like c++shell, jdoodle or onlineGDB or any other and run it to observe the output. Then read the comments or description below. The class names are written such that after the underscore I give the keyword related to it.

AbstractProduct
The abstract product is an abstract class and as expected it defines a family of products that inherit from it. In this example, the abstract product is aDoorHandle, I added a function that prints something for the purposes of showcasing.

#include <iostream>class DoorHandle_AbstractProduct
{
public:
// A dummy function that prints something
virtual void printSerialNumber() = 0;
};

Product
In this example, the products are BMW or Ford door handle. They have different serial numbers, therefore, each class can print their own product-specific serial number. We could also have DoorWindoworSteeringWheel. The door handle classes inherit from the abstract class above.

// BMW door handle [in the family of doorHandles]
class BMWDoorHandle_Product : public DoorHandle_AbstractProduct
{
public:
// Prints product-specific serial number
void printSerialNumber (){
std::cout << " DoorHandle_Product: BMW123 \n";
}
};
// Ford door handle [in the family of doorHandles]
class FordDoorHandle_Product : public DoorHandle_AbstractProduct
{
public:
// Prints product-specific serial number
void printSerialNumber (){
std::cout << " DoorHandle_Product: Ford123 \n";
}
};

AbstracFactory
This is a very generic/abstract class which should not have much more than the createfunctions. In the end, a factory is just creating products.

class Car_AbstractFactory 
{
public:
virtual DoorHandle_AbstractProduct* createDoorHandle () = 0;
//virtual DoorWindow_AbstractProduct* createDoorWindow () = 0;
};

ConcreteFactory
This factory class is quite specific to the product. It is the hard worker that puts the puzzle together. In this example, it is specific to a brand {BMW, Ford}. Its job is to return an instance of a product which is specific to that brand. Again, if we wanted to createBMWDoorWindow we could actually create a new function that returns an instance of the relevant abstract class. In my git repository, there is the full implementation with theDoorWindow parts as well.

class BMWCar_ConcreteFactory : public Car_AbstractFactory 
{
public:
DoorHandle_AbstractProduct* createDoorHandle (){
return new BMWDoorHandle_Product;
}
};
class FordCar_ConcreteFactory : public Car_AbstractFactory
{
public:
DoorHandle_AbstractProduct* createDoorHandle (){
return new FordDoorHandle_Product;
}
};

Main function
Finally, this is the last piece of code. The main function which operates as the client. The client can easily “order” products from the factory and can use them in any way he likes.

int main()
{
// Client needs a doorHandle and a doorWindow
Car_AbstractFactory* abstractFactory;
DoorHandle_AbstractProduct* dHandle_AbstractProduct;

// The client needs products from Ford brand
abstractFactory = new FordCar_ConcreteFactory;
// Ford concrete factory creates them
// and returns them to the client
dHandle_AbstractProduct = abstractFactory->createDoorHandle();
// Client uses the products
dHandle_AbstractProduct -> printSerialNumber();
// Now the client wants products but from BMW brand
abstractFactory = new BMWCar_ConcreteFactory;
// So the BMW concrete factory creates them
// and returns them to the client
dHandle_AbstractProduct = abstractFactory->createDoorHandle();
// Client uses the products
dHandle_AbstractProduct -> printSerialNumber();
return 0;
}
// Output
// DoorHandle_Product: Ford123
// DoorHandle_Product: BMW123

Benefits might not be instantly obvious. But imagine for a second how many products a car has and how many things can a car factory do. Now imagine the chaos maintaining a badly designed code every time BMW decides to alter a door handle. Add a new type of driver-seat or even change something in the engine. Now adding to the complexity, imagine maintaining these problems but for multiple brands. Abstract factory offers a maintainable and clean approach, that can be used for years to come. It would be difficult for a new developer to mess up and so easy to add/remove a new product.

Abstract factory is just the beginning of this journey. This is one of the most commonly used design patterns and many times it is used in combination with other design patterns. The next blog will be a quick-guide to Singleton design pattern. Don’t forget to like my blog and follow my account. This is to give me the satisfaction that I helped some fellow developers and push me to keep on writing.

Other quick-guides on design patterns:

  1. Design Patterns — A quick guide to Abstract Factory.
  2. Design Patterns — A quick guide to Bridge Pattern.
  3. Design Patterns — A quick guide to Builder Pattern.
  4. Design Patterns — A quick guide to Decorator Pattern.
  5. Design Patterns — A quick guide to Facade Pattern.
  6. Design Patterns — A quick guide to Observer Pattern.
  7. Design Patterns — A quick guide to Singleton Pattern.

--

--

Andreas Poyias

PhD in the development of data mining algorithms. I am a proud nerd that loves technology!