Home [Design Patterns] Abstract Factory Pattern
Post
Cancel

[Design Patterns] Abstract Factory Pattern

Definition

The abstract factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

The abstract factory pattern and the factory method pattern are really alike, except that the former one constructs multiple objects, and the latter one constructs a single object.

Scenario

We have different categories, and under each category, there are different products for different cases. For example, an application wants to create a cross-platform UI. It needs to build UI components (e.g., buttons and text boxes) for Linux, Mac, and Windows. We can group concrete UI components of these three OS and then create an abstract factory to choose which should pair up, like Linux button should pair up with Linux text box.

Class Diagram

Abstract Factory Pattern Abstract Factory Pattern

We delegate the creation of UIs (IButton and ITextBox) to UIFactory method GetButton and GetTextBox. The concrete factory (LinuxUIFactory and MacUIFactory) creates specific objects by implementing those object creation methods. Thus, different UIs are grouped together when get called.

Used Cases

  • For different themes (e.g., color and fonts), we can group the creation of a family of UIs (e.g., buttons and text boxes) using a factory.
  • We need to group products in the same category and want them to pair up in specific combinations.

Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// abstract_factory.h
#ifndef __ABSTRACT_FACTORY_H__
#define __ABSTRACT_FACTORY_H__

#include <iostream>
#include <memory>

class IButton {
protected:
    std::string name_;

public:
    IButton(const std::string&& name) : name_(name) {}
    virtual void PrintName();
};

class LinuxButton : public IButton {
public:
    LinuxButton() : IButton("Linux Button") {}
};

class MacButton : public IButton {
public:
    MacButton() : IButton("Mac Button") {}
};

class ITextBox {
protected:
    std::string name_;

public:
    ITextBox(const std::string&& name) : name_(name) {}
    virtual void PrintName();
};

class LinuxTextBox : public ITextBox {
public:
    LinuxTextBox() : ITextBox("Linux TextBox") {}
};

class MacTextBox : public ITextBox {
public:
    MacTextBox() : ITextBox("Mac TextBox") {}
};

class UIFactory {
public:
    virtual std::unique_ptr<IButton> GetButton() = 0;
    virtual std::unique_ptr<ITextBox> GetTextBox() = 0;
};

class LinuxUIFactory : public UIFactory {
public:
    std::unique_ptr<IButton> GetButton() override;
    std::unique_ptr<ITextBox> GetTextBox() override;
};

class MacUIFactory : public UIFactory {
public:
    std::unique_ptr<IButton> GetButton() override;
    std::unique_ptr<ITextBox> GetTextBox() override;
};

#endif  //__ABSTRACT_FACTORY_H__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// abstract_factory.cpp
#include "abstract_factory.h"

void IButton::PrintName() { std::cout << "Button: " << name_ << std::endl; }

void ITextBox::PrintName() { std::cout << "TextBox: " << name_ << std::endl; }

std::unique_ptr<IButton> LinuxUIFactory::GetButton() { return std::make_unique<LinuxButton>(); }

std::unique_ptr<ITextBox> LinuxUIFactory::GetTextBox() { return std::make_unique<LinuxTextBox>(); }

std::unique_ptr<IButton> MacUIFactory::GetButton() { return std::make_unique<MacButton>(); }

std::unique_ptr<ITextBox> MacUIFactory::GetTextBox() { return std::make_unique<MacTextBox>(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// main.cpp

#include "abstract_factory.h"

int main() {
    {
        std::unique_ptr<UIFactory> ui_factory = std::make_unique<LinuxUIFactory>();
        std::unique_ptr<IButton> button = ui_factory->GetButton();
        std::unique_ptr<ITextBox> textbox = ui_factory->GetTextBox();

        button->PrintName();
        textbox->PrintName();
    }
    return 0;
}

Reference

This post is licensed under CC BY 4.0 by the author.