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+ << " \t sudo 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 << " \t pacman -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 << " \t brew 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