Skip to content

Commit 1f17733

Browse files
committed
Add the FactoryMethod pattern
1 parent 2219ec8 commit 1f17733

3 files changed

Lines changed: 178 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ set(APP_SOURCES
109109
"src/patterns/behavioral/State.cpp"
110110
"src/patterns/behavioral/Observer.cpp"
111111
"src/patterns/creational/Singleton.cpp"
112+
"src/patterns/creational/FactoryMethod.cpp"
112113
)
113114

114115
# Test files

docs/uml/patterns_creational_factorymethod.drawio.svg

Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// cppcheck-suppress-file [functionStatic]
2+
3+
// Factory Method is a creational design pattern that provides an interface for creating objects in a superclass,
4+
// but allows subclasses to alter the type of objects that will be created.
5+
// Appicability:
6+
// (*) when you don’t know beforehand the exact types and dependencies of the objects your code should work with.
7+
// (**) when you want to provide users of your library or framework with a way to extend its internal components.
8+
// (***)when you want to save system resources by reusing existing objects instead of rebuilding them each time.
9+
// UML: docs/uml/patterns_creational_factorymethod.drawio.svg
10+
11+
#include <iostream>
12+
#include <string>
13+
namespace
14+
{
15+
namespace FactoryMethod
16+
{
17+
/**
18+
* The Product interface declares the operations that all concrete products must
19+
* implement.
20+
*/
21+
class IGdbProduct
22+
{
23+
public:
24+
virtual ~IGdbProduct() = default;
25+
virtual void launch() const = 0;
26+
};
27+
28+
/**
29+
* Concrete Products provide various implementations of the Product interface.
30+
*/
31+
class LinuxGdbProduct : public IGdbProduct
32+
{
33+
public:
34+
void launch() const override
35+
{
36+
std::cout
37+
<< "\tsudo apt update && sudo apt install -y gdb && gdb --version\n";
38+
}
39+
};
40+
41+
class WindowsGdbProduct : public IGdbProduct
42+
{
43+
public:
44+
void launch() const override
45+
{
46+
std::cout << "\tpacman -Syu mingw-w64-x86_64-gdb && gdb --version\n";
47+
}
48+
};
49+
50+
class MacOsGdbProduct : public IGdbProduct
51+
{
52+
public:
53+
void launch() const override
54+
{
55+
std::cout << "\tbrew install gdb && gdb --version\n";
56+
}
57+
};
58+
59+
/**
60+
* The Creator class declares the factory method that is supposed to return an
61+
* object of a Product class. The Creator's subclasses usually provide the
62+
* implementation of this method.
63+
*/
64+
class IGdbCreator
65+
{
66+
public:
67+
virtual ~IGdbCreator() = default;
68+
virtual IGdbProduct *factoryMethod() = 0;
69+
virtual void launchGdb() = 0;
70+
};
71+
72+
class AbstractGdbCreater : public IGdbCreator
73+
{
74+
public:
75+
// Call the factory method to create a Product object.
76+
77+
void launchGdb() override final
78+
{
79+
IGdbProduct *gdb = this->factoryMethod();
80+
gdb->launch();
81+
delete gdb;
82+
}
83+
};
84+
85+
/**
86+
* Concrete Creators override the factory method in order to change the
87+
* resulting product's type.
88+
*/
89+
class WindowsGdbCreator : public AbstractGdbCreater
90+
{
91+
public:
92+
IGdbProduct *factoryMethod() override
93+
{
94+
return new WindowsGdbProduct();
95+
}
96+
};
97+
98+
class LinuxGdbCreator : public AbstractGdbCreater
99+
{
100+
public:
101+
IGdbProduct *factoryMethod() override
102+
{
103+
return new LinuxGdbProduct();
104+
}
105+
};
106+
107+
class MacOsGdbCreator : public AbstractGdbCreater
108+
{
109+
public:
110+
IGdbProduct *factoryMethod() override
111+
{
112+
return new MacOsGdbProduct();
113+
}
114+
};
115+
116+
/**
117+
* The client code works with an instance of a concrete creator, albeit through its base interface.
118+
* As long as the client keeps working with the creator via the base interface, you can pass it any creator's subclass.
119+
*/
120+
namespace ClientCode
121+
{
122+
void clientCode(IGdbCreator *gdb)
123+
{
124+
if (gdb != nullptr)
125+
gdb->launchGdb();
126+
}
127+
}
128+
129+
class GdbCreatorFactory
130+
{
131+
public:
132+
static IGdbCreator *createGdbCreator(const std::string &os)
133+
{
134+
if (os == "linux")
135+
{
136+
return new LinuxGdbCreator();
137+
}
138+
else if (os == "windows")
139+
{
140+
return new WindowsGdbCreator();
141+
}
142+
else if (os == "macos")
143+
{
144+
return new MacOsGdbCreator();
145+
}
146+
else
147+
{
148+
std::cout << "OS not support yet - " << os << "\n";
149+
return nullptr;
150+
}
151+
}
152+
};
153+
154+
void run()
155+
{
156+
std::string os = "linux";
157+
IGdbCreator *gdb = GdbCreatorFactory::createGdbCreator(os);
158+
ClientCode::clientCode(gdb);
159+
delete gdb;
160+
}
161+
}
162+
}
163+
164+
struct FactoryMethodAutoRunner
165+
{
166+
FactoryMethodAutoRunner()
167+
{
168+
std::cout << "\n--- FactoryMethod Pattern Example ---\n";
169+
FactoryMethod::run();
170+
}
171+
};
172+
173+
static FactoryMethodAutoRunner instance;

0 commit comments

Comments
 (0)