-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathConceptualExample.cpp
More file actions
160 lines (134 loc) · 5.29 KB
/
Copy pathConceptualExample.cpp
File metadata and controls
160 lines (134 loc) · 5.29 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
// ===========================================================================
// ConceptualExample.cpp // Abstract Factory
// ===========================================================================
//#include <iostream>
#include <string>
#include <memory>
#include <map>
#include <print>
namespace ConceptualExample_Abstract_Factory_Pattern {
/**
* Each distinct product of a product family should have a base interface.
* All variants of this product must implement this interface.
*/
class AbstractProductA {
public:
virtual ~AbstractProductA() = default;
virtual std::string usefulFunctionA() const = 0;
};
// =======================================================================
/**
* Concrete Products are created by corresponding Concrete Factories.
*/
class ConcreteProductA1 : public AbstractProductA
{
public:
std::string usefulFunctionA() const override {
return "Working on Concrete Product A1";
}
};
class ConcreteProductA2 : public AbstractProductA
{
public:
std::string usefulFunctionA() const override {
return "Working on Concrete Product A2";
}
};
// =======================================================================
/**
* Here's the the base interface of another product. All products can interact
* with each other, but proper interaction is possible only between products of
* the same concrete variant.
*/
class AbstractProductB {
/**
* Product B is able to do its own thing...
*/
public:
virtual ~AbstractProductB() = default;
virtual std::string usefulFunctionB() const = 0;
};
/**
* Concrete Products are created by corresponding Concrete Factories.
*/
class ConcreteProductB1 : public AbstractProductB {
public:
std::string usefulFunctionB() const override {
return "Working on Concrete Product B1";
}
};
class ConcreteProductB2 : public AbstractProductB {
public:
std::string usefulFunctionB() const override {
return "Working on Concrete Product B2";
}
};
// ===========================================================================
/**
* The Abstract Factory interface declares a set of methods that return
* different abstract products. These products are called a family and are
* related by a high-level theme or concept.
* A family of products may have seveveral variants, but the products
* of one variant are incompatible with products of another.
*/
class AbstractFactory {
public:
virtual std::shared_ptr<AbstractProductA> createProductA() const = 0;
virtual std::shared_ptr<AbstractProductB> createProductB() const = 0;
};
/**
* Concrete Factories produce a family of products that belong to a single
* variant. The factory guarantees that resulting products are compatible.
*
* NOTE: Signatures of the Concrete Factory's methods return an abstract product,
* while inside the method a concrete product is instantiated.
*/
class ConcreteFactory1 : public AbstractFactory {
public:
std::shared_ptr<AbstractProductA> createProductA() const override {
return std::make_shared<ConcreteProductA1>(); // <== concrete product returned
}
std::shared_ptr<AbstractProductB> createProductB() const override {
return std::make_shared<ConcreteProductB1>(); // <== concrete product returned
}
};
/**
* Each Concrete Factory has a corresponding product variant.
*/
class ConcreteFactory2 : public AbstractFactory {
public:
std::shared_ptr<AbstractProductA> createProductA() const override {
return std::make_shared<ConcreteProductA2>(); // <== concrete product returned
}
std::shared_ptr<AbstractProductB> createProductB() const override {
return std::make_shared<ConcreteProductB2>(); // <== concrete product returned
}
};
// ===========================================================================
/**
* The client code works with factories and products only through abstract types:
* AbstractFactory and AbstractProduct. This lets you pass any factory or
* product subclass to the client code without breaking it.
*/
static void clientCode(const AbstractFactory& factory)
{
const std::shared_ptr<AbstractProductA> product_a{ factory.createProductA() };
const std::shared_ptr<AbstractProductB> product_b{ factory.createProductB() };
std::println("{}", product_a->usefulFunctionA());
std::println("{}", product_b->usefulFunctionB());
}
}
void test_conceptual_example()
{
using namespace ConceptualExample_Abstract_Factory_Pattern;
std::println("Client: Testing client code with the first factory type:");
ConcreteFactory1 f1;
clientCode(f1);
std::println();
std::println("Client: Testing the same client code with the second factory type:");
ConcreteFactory2 f2;
clientCode(f2);
}
// ===========================================================================
// End-of-File
// ===========================================================================