-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathConceptualExample.cpp
More file actions
143 lines (122 loc) · 4.51 KB
/
ConceptualExample.cpp
File metadata and controls
143 lines (122 loc) · 4.51 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
// ===========================================================================
// ConceptualExample.cpp // Template Method
// ===========================================================================
#include <iostream>
#include <memory>
/**
* The Abstract Class defines a template method that contains a skeleton of some
* algorithm, composed of calls to (usually) abstract primitive operations.
*
* Concrete subclasses should implement these operations, but leave the template
* method itself intact.
*/
class AbstractClass {
public:
/**
* The template method defines the skeleton of an algorithm:
*/
void TemplateMethod() const
{
BaseOperation1(); // may be overriden, but it's not mandatory
if (RequiredOperations1()) { // MUST be overriden
BaseOperation2(); // may be overriden, but it's not mandatory
Hook1(); // may be overriden, but it's not mandatory
}
else
{
RequiredOperation2(); // MUST be overriden
BaseOperation3(); // may be overriden, but it's not mandatory
Hook2(); // may be overriden, but it's not mandatory
}
}
/**
* These operations already have implementations.
*/
protected:
virtual void BaseOperation1() const {
std::cout << "AbstractClass says: I am doing the bulk of the work" << std::endl;
}
virtual void BaseOperation2() const {
std::cout << "AbstractClass says: But I let subclasses override some operations" << std::endl;
}
virtual void BaseOperation3() const {
std::cout << "AbstractClass says: But I am doing the bulk of the work anyway" << std::endl;
}
/**
* These operations have to be implemented in subclasses.
*/
virtual bool RequiredOperations1() const = 0;
virtual bool RequiredOperation2() const = 0;
/**
* These are "hooks." Subclasses may override them, but it's not mandatory
* since the hooks already have default (but empty) implementation.
* Hooks provide additional extension points in some crucial places of the
* algorithm.
*/
virtual void Hook1() const {}
virtual void Hook2() const {}
};
/**
* Concrete classes have to implement all abstract operations of the base class.
* They can also override some operations with a default implementation.
*/
class ConcreteClass1 : public AbstractClass {
protected:
bool RequiredOperations1() const override {
std::cout << "ConcreteClass1 says: Implemented Operation1" << std::endl;
return false;
}
bool RequiredOperation2() const override {
std::cout << "ConcreteClass1 says: Implemented Operation2" << std::endl;
return false;
}
};
/**
* Usually, concrete classes override only a fraction of base class' operations.
*/
class ConcreteClass2 : public AbstractClass {
protected:
bool RequiredOperations1() const override {
std::cout << "ConcreteClass2 says: Implemented Operation1" << std::endl;
return true;
}
bool RequiredOperation2() const override {
std::cout << "ConcreteClass2 says: Implemented Operation2" << std::endl;
return true;
}
void BaseOperation1() const override {
std::cout << "ConcreteClass2 says: Overridden BaseOperation1" << std::endl;
}
void Hook1() const override {
std::cout << "ConcreteClass2 says: Overridden Hook1" << std::endl;
}
};
/**
* The client code calls the template method to execute the algorithm. Client
* code does not have to know the concrete class of an object it works with, as
* long as it works with objects through the interface of their base class.
*/
static void clientCode(const std::shared_ptr<AbstractClass>& obj) {
// ...
obj->TemplateMethod();
// ...
}
void test_conceptual_example() {
std::cout << "Same client code can work with different subclasses (1):" << std::endl;
std::shared_ptr<AbstractClass> concreteClass1
{
std::make_shared<ConcreteClass1>()
};
clientCode(concreteClass1);
std::cout << std::endl;
std::cout << "Same client code can work with different subclasses (2):" << std::endl;
std::shared_ptr<AbstractClass> concreteClass2
{
std::make_shared<ConcreteClass2>()
};
clientCode(concreteClass2);
std::cout << std::endl;
}
// ===========================================================================
// End-of-File
// ===========================================================================