-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAbstractFactory.cpp
More file actions
173 lines (151 loc) · 4.73 KB
/
Copy pathAbstractFactory.cpp
File metadata and controls
173 lines (151 loc) · 4.73 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// cppcheck-suppress-file [functionStatic]
// Abstract Factory is a creational design pattern that lets you produce
// families of related objects without specifying their concrete classes.
// Appicability:
// (*) when your code needs to work with various families of related products,
// but you don’t want it to depend on the concrete classes
// of those products—they might be unknown beforehand or you simply want to
// allow for future extensibility.
// (**) when you have a class with a set of Factory Methods that blur its
// primary responsibility.
// UML: docs/uml/patterns_creational_abstractfactory.drawio.svg
#include <iostream>
#include <string>
namespace {
namespace AbstractFactory {
/**
* The Product interface declares the operations that all concrete products must
* implement.
*/
class IGdbProduct {
public:
virtual ~IGdbProduct() = default;
virtual void launch() const = 0;
};
/**
* Concrete Products provide various implementations of the Product interface.
*/
class LinuxGdbProduct : public IGdbProduct {
public:
void launch() const override {
std::cout
<< "\tsudo apt update && sudo apt install -y gdb && gdb --version\n";
}
};
class WindowsGdbProduct : public IGdbProduct {
public:
void launch() const override {
std::cout << "\tpacman -Syu mingw-w64-x86_64-gdb && gdb --version\n";
}
};
class MacOsGdbProduct : public IGdbProduct {
public:
void launch() const override {
std::cout << "\tbrew install gdb && gdb --version\n";
}
};
class ICMakeProduct {
public:
virtual ~ICMakeProduct() = default;
virtual void launch() const = 0;
};
class LinuxCMakeProduct : public ICMakeProduct {
public:
void launch() const override {
std::cout << "\tsudo apt update && sudo apt install -y cmake && cmake "
"--version\n";
}
};
class WindowsCMakeProduct : public ICMakeProduct {
public:
void launch() const override {
std::cout << "\tpacman -Syu cmake && cmake --version\n";
}
};
class MacOsCMakeProduct : public ICMakeProduct {
public:
void launch() const override {
std::cout << "\tbrew install cmake && cmake --version\n";
}
};
// ===================================================================================
/*
* Abstract Factory
* provides an abstract interface for creating a family of products
*/
class IProductAbstractFactory {
public:
virtual ~IProductAbstractFactory() = default;
virtual IGdbProduct* createGdbProduct() = 0;
virtual ICMakeProduct* createCMakeProduct() = 0;
};
/*
* Concrete Factory
* each concrete factory create a family of products and client uses
* one of these factories so it never has to instantiate a product object
*/
class WindowsProductFactory : public IProductAbstractFactory {
public:
IGdbProduct* createGdbProduct() override { return new WindowsGdbProduct(); }
ICMakeProduct* createCMakeProduct() override {
return new WindowsCMakeProduct();
}
};
class LinuxProductFactory : public IProductAbstractFactory {
public:
IGdbProduct* createGdbProduct() override { return new LinuxGdbProduct(); }
ICMakeProduct* createCMakeProduct() override {
return new LinuxCMakeProduct();
}
};
class MacOsProductFactory : public IProductAbstractFactory {
public:
IGdbProduct* createGdbProduct() override { return new MacOsGdbProduct(); }
ICMakeProduct* createCMakeProduct() override {
return new MacOsCMakeProduct();
}
};
// ===================================================================================
/**
* The client code works with factories and products only through abstract
* types: AbstractFactory and AbstractProduct. This lets you pass any factory or
* product subclass to the client code without breaking it.
*/
namespace ClientCode {
void clientCode(IProductAbstractFactory* f) {
ICMakeProduct* cmake = f->createCMakeProduct();
IGdbProduct* gdb = f->createGdbProduct();
cmake->launch();
gdb->launch();
delete cmake;
delete gdb;
}
} // namespace ClientCode
// static redudant inside anonymous namespace
IProductAbstractFactory* createProductFactory(const std::string& os) {
if (os == "linux") {
return new LinuxProductFactory();
} else if (os == "windows") {
return new WindowsProductFactory();
} else if (os == "macos") {
return new MacOsProductFactory();
} else {
std::cout << "OS not support yet - " << os << "\n";
return nullptr;
}
}
void run() {
std::string os = "linux";
IProductAbstractFactory* factory = createProductFactory(os);
ClientCode::clientCode(factory);
delete factory;
}
} // namespace AbstractFactory
} // namespace
struct AbstractFactoryAutoRunner {
AbstractFactoryAutoRunner() {
std::cout << "\n--- AbstractFactory Pattern Example ---\n";
AbstractFactory::run();
}
};
static AbstractFactoryAutoRunner instance;