-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFactoryMethod.cpp
More file actions
140 lines (122 loc) · 3.84 KB
/
FactoryMethod.cpp
File metadata and controls
140 lines (122 loc) · 3.84 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
// cppcheck-suppress-file [functionStatic]
// Factory Method is a creational design pattern that provides an interface for
// creating objects in a superclass, but allows subclasses to alter the type of
// objects that will be created. Appicability:
// (*) when you don’t know beforehand the exact types and dependencies of the
// objects your code should work with.
// (**) when you want to provide users of your library or framework with a way
// to extend its internal components.
// (***)when you want to save system resources by reusing existing objects
// instead of rebuilding them each time.
// UML: docs/uml/patterns_creational_factorymethod.drawio.svg
#include <iostream>
#include <string>
namespace {
namespace FactoryMethod {
/**
* 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";
}
};
// ===================================================================================
/**
* The Creator class declares the factory method that is supposed to return an
* object of a Product class. The Creator's subclasses usually provide the
* implementation of this method. (a.k.a IGdbFactory)
*/
class IGdbFactory {
public:
virtual ~IGdbFactory() = default;
virtual IGdbProduct* factoryMethod() = 0;
virtual void launchGdb() = 0;
};
class AbstractGdbFactory : public IGdbFactory {
public:
// Call the factory method to create a Product object.
void launchGdb() override final {
IGdbProduct* gdb = this->factoryMethod();
gdb->launch();
delete gdb;
}
};
/**
* Concrete Creators override the factory method in order to change the
* resulting product's type.
*/
class WindowsGdbFactory : public AbstractGdbFactory {
public:
IGdbProduct* factoryMethod() override { return new WindowsGdbProduct(); }
};
class LinuxGdbFactory : public AbstractGdbFactory {
public:
IGdbProduct* factoryMethod() override { return new LinuxGdbProduct(); }
};
class MacOsGdbFactory : public AbstractGdbFactory {
public:
IGdbProduct* factoryMethod() override { return new MacOsGdbProduct(); }
};
// ===================================================================================
/**
* The client code works with an instance of a concrete creator, albeit through
* its base interface. As long as the client keeps working with the creator via
* the base interface, you can pass it any creator's subclass.
*/
namespace ClientCode {
void clientCode(IGdbFactory* gdb) {
if (gdb != nullptr)
gdb->launchGdb();
}
} // namespace ClientCode
IGdbFactory* createGdbFactory(const std::string& os) {
if (os == "linux") {
return new LinuxGdbFactory();
} else if (os == "windows") {
return new WindowsGdbFactory();
} else if (os == "macos") {
return new MacOsGdbFactory();
} else {
std::cout << "OS not support yet - " << os << "\n";
return nullptr;
}
}
void run() {
std::string os = "linux";
IGdbFactory* gdb = createGdbFactory(os);
ClientCode::clientCode(gdb);
delete gdb;
}
} // namespace FactoryMethod
} // namespace
struct FactoryMethodAutoRunner {
FactoryMethodAutoRunner() {
std::cout << "\n--- FactoryMethod Pattern Example ---\n";
FactoryMethod::run();
}
};
static FactoryMethodAutoRunner instance;