44// families of related objects without specifying their concrete classes.
55// Appicability:
66// (*) when your code needs to work with various families of related products,
7- // but you don’t want it to depend on the concrete classes
7+ // but you don’t want it to depend on the concrete classes
88// of those products—they might be unknown beforehand or you simply want to
99// allow for future extensibility.
1010// (**) when you have a class with a set of Factory Methods that blur its
11- // primary responsibility.
11+ // primary responsibility.
1212
13- // UML: docs/uml/patterns_behavioral_iterator .drawio.svg
13+ // UML: docs/uml/patterns_creational_abstractfactory .drawio.svg
1414
1515#include < iostream>
16+ #include < string>
17+ namespace {
18+ namespace AbstractFactory {
19+ /* *
20+ * The Product interface declares the operations that all concrete products must
21+ * implement.
22+ */
23+ class IGdbProduct {
24+ public:
25+ virtual ~IGdbProduct () = default ;
26+ virtual void launch () const = 0;
27+ };
1628
17- namespace {}
29+ /* *
30+ * Concrete Products provide various implementations of the Product interface.
31+ */
32+ class LinuxGdbProduct : public IGdbProduct {
33+ public:
34+ void launch () const override {
35+ std::cout
36+ << " \t sudo apt update && sudo apt install -y gdb && gdb --version\n " ;
37+ }
38+ };
1839
19- // struct SingletonAutoRuner
20- // {
21- // SingletonAutoRuner()
22- // {
23- // std::cout << "\n--- Singleton Pattern Example ---\n";
24- // }
25- // };
40+ class WindowsGdbProduct : public IGdbProduct {
41+ public:
42+ void launch () const override {
43+ std::cout << " \t pacman -Syu mingw-w64-x86_64-gdb && gdb --version\n " ;
44+ }
45+ };
2646
27- // static SingletonAutoRuner instance;
47+ class MacOsGdbProduct : public IGdbProduct {
48+ public:
49+ void launch () const override {
50+ std::cout << " \t brew install gdb && gdb --version\n " ;
51+ }
52+ };
53+
54+ class ICMakeProduct {
55+ public:
56+ virtual ~ICMakeProduct () = default ;
57+ virtual void launch () const = 0;
58+ };
59+
60+ class LinuxCMakeProduct : public ICMakeProduct {
61+ public:
62+ void launch () const override {
63+ std::cout << " \t sudo apt update && sudo apt install -y cmake && cmake "
64+ " --version\n " ;
65+ }
66+ };
67+
68+ class WindowsCMakeProduct : public ICMakeProduct {
69+ public:
70+ void launch () const override {
71+ std::cout << " \t pacman -Syu cmake && cmake --version\n " ;
72+ }
73+ };
74+
75+ class MacOsCMakeProduct : public ICMakeProduct {
76+ public:
77+ void launch () const override {
78+ std::cout << " \t brew install cmake && cmake --version\n " ;
79+ }
80+ };
81+
82+ // ===================================================================================
83+
84+ /*
85+ * Abstract Factory
86+ * provides an abstract interface for creating a family of products
87+ */
88+ class IProductAbstractFactory {
89+ public:
90+ virtual ~IProductAbstractFactory () = default ;
91+ virtual IGdbProduct* createGdbProduct () = 0;
92+ virtual ICMakeProduct* createCMakeProduct () = 0;
93+ };
94+
95+ /*
96+ * Concrete Factory
97+ * each concrete factory create a family of products and client uses
98+ * one of these factories so it never has to instantiate a product object
99+ */
100+ class WindowsProductFactory : public IProductAbstractFactory {
101+ public:
102+ IGdbProduct* createGdbProduct () override { return new WindowsGdbProduct (); }
103+ ICMakeProduct* createCMakeProduct () override {
104+ return new WindowsCMakeProduct ();
105+ }
106+ };
107+
108+ class LinuxProductFactory : public IProductAbstractFactory {
109+ public:
110+ IGdbProduct* createGdbProduct () override { return new LinuxGdbProduct (); }
111+ ICMakeProduct* createCMakeProduct () override {
112+ return new LinuxCMakeProduct ();
113+ }
114+ };
115+
116+ class MacOsProductFactory : public IProductAbstractFactory {
117+ public:
118+ IGdbProduct* createGdbProduct () override { return new MacOsGdbProduct (); }
119+ ICMakeProduct* createCMakeProduct () override {
120+ return new MacOsCMakeProduct ();
121+ }
122+ };
123+
124+ // ===================================================================================
125+
126+ /* *
127+ * The client code works with factories and products only through abstract
128+ * types: AbstractFactory and AbstractProduct. This lets you pass any factory or
129+ * product subclass to the client code without breaking it.
130+ */
131+ namespace ClientCode {
132+ void clientCode (IProductAbstractFactory* f) {
133+ ICMakeProduct* cmake = f->createCMakeProduct ();
134+ IGdbProduct* gdb = f->createGdbProduct ();
135+ cmake->launch ();
136+ gdb->launch ();
137+
138+ delete cmake;
139+ delete gdb;
140+ }
141+ } // namespace ClientCode
142+
143+ // static redudant inside anonymous namespace
144+ IProductAbstractFactory* createProductFactory (const std::string& os) {
145+ if (os == " linux" ) {
146+ return new LinuxProductFactory ();
147+ } else if (os == " windows" ) {
148+ return new WindowsProductFactory ();
149+ } else if (os == " macos" ) {
150+ return new MacOsProductFactory ();
151+ } else {
152+ std::cout << " OS not support yet - " << os << " \n " ;
153+ return nullptr ;
154+ }
155+ }
156+
157+ void run () {
158+ std::string os = " linux" ;
159+ IProductAbstractFactory* factory = createProductFactory (os);
160+ ClientCode::clientCode (factory);
161+ delete factory;
162+ }
163+ } // namespace AbstractFactory
164+ } // namespace
165+
166+ struct AbstractFactoryAutoRunner {
167+ AbstractFactoryAutoRunner () {
168+ std::cout << " \n --- AbstractFactory Pattern Example ---\n " ;
169+ AbstractFactory::run ();
170+ }
171+ };
172+
173+ static AbstractFactoryAutoRunner instance;
0 commit comments