-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFactoryMethod.cpp
More file actions
174 lines (157 loc) · 4.98 KB
/
Copy pathFactoryMethod.cpp
File metadata and controls
174 lines (157 loc) · 4.98 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
174
// 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.
*/
class IGdbCreator
{
public:
virtual ~IGdbCreator() = default;
virtual IGdbProduct *factoryMethod() = 0;
virtual void launchGdb() = 0;
};
class AbstractGdbCreater : public IGdbCreator
{
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 WindowsGdbCreator : public AbstractGdbCreater
{
public:
IGdbProduct *factoryMethod() override
{
return new WindowsGdbProduct();
}
};
class LinuxGdbCreator : public AbstractGdbCreater
{
public:
IGdbProduct *factoryMethod() override
{
return new LinuxGdbProduct();
}
};
class MacOsGdbCreator : public AbstractGdbCreater
{
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(IGdbCreator *gdb)
{
if (gdb != nullptr)
gdb->launchGdb();
}
}
class GdbCreatorFactory
{
public:
static IGdbCreator *createGdbCreator(const std::string &os)
{
if (os == "linux")
{
return new LinuxGdbCreator();
}
else if (os == "windows")
{
return new WindowsGdbCreator();
}
else if (os == "macos")
{
return new MacOsGdbCreator();
}
else
{
std::cout << "OS not support yet - " << os << "\n";
return nullptr;
}
}
};
void run()
{
std::string os = "linux";
IGdbCreator *gdb = GdbCreatorFactory::createGdbCreator(os);
ClientCode::clientCode(gdb);
delete gdb;
}
}
}
struct FactoryMethodAutoRunner
{
FactoryMethodAutoRunner()
{
std::cout << "\n--- FactoryMethod Pattern Example ---\n";
FactoryMethod::run();
}
};
static FactoryMethodAutoRunner instance;