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
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;
}