forked from caiorss/C-Cpp-Notes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
composite1.cpp
186 lines (161 loc) · 4.8 KB
/
composite1.cpp
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Brief: Composite Design Pattern
// Author: Caio Rodrigues
//----------------------------------------------
#include <iostream>
#include <memory>
#include <vector>
#include <deque>
// Interface ->
class IGraphic{
public:
virtual auto type() const -> const std::string = 0;
virtual auto draw() -> void = 0;
virtual auto rotate(double) -> void = 0;
virtual ~IGraphic() = default;
};
using cstring = const char*;
using GNode = std::shared_ptr<IGraphic>;
class Group: public IGraphic{
private:
std::vector<GNode> _nodes;
const std::string _id;
static constexpr cstring _type = "Group";
public:
Group(const std::string& id): _id(id) {
std::cout << " [TRACE] Create group = " << id << "\n";
}
~Group(){
std::cout << " [TRACE] Destroy group - id = << " << _id << "\n";
}
auto begin() const -> decltype(_nodes.begin()) {
return _nodes.begin();
}
auto end() const -> decltype(_nodes.end()) {
return _nodes.end();
}
auto clear() -> void {
_nodes.clear();
}
auto size() -> size_t {
return _nodes.size();
}
auto add(GNode n) -> void {
std::cout << " [TRACE] id = " << _id
<< "; Add object = " << n->type() << "\n";
_nodes.push_back(n);
}
auto add(IGraphic* n) -> void {
std::cout << " [TRACE] id = " << _id
<< " ; Add object = " << n->type() << "\n";
_nodes.push_back(std::shared_ptr<IGraphic>(n));
}
// Add stack-allocated object
auto addFromStack(IGraphic* n) -> void {
std::cout << " [TRACE] id = " << _id
<< " ; Add object = " << n->type() << "\n";
// Dummy deleter to avoid core dump by avoiding deleting
// stack-allocated object or non-owned pointer.
auto s = std::shared_ptr<IGraphic>(n, [](IGraphic*){ return ; });
_nodes.push_back(s);
}
// Note: Template methods should always be in the header files
template<class Node>
auto addNew(const std::string& id) -> void {
auto n = std::make_unique<Node>(id);
std::cout << " [TRACE] id = " << _id
<< " ; Add object = " << n->type() << "\n";
_nodes.push_back(std::move(n));
}
// ======> Interface IGraphic <<=========//
auto type() const -> const std::string override {
return _type;
}
auto draw() -> void override {
std::cout << " [TRACE] Draw group - id = " << _id << "\n";
for(const auto& obj: _nodes)
obj->draw();
}
auto rotate(double angle) -> void override {
std::cout << " [TRACE] Rotate group - id = " << _id << "\n";
for(const auto& obj: _nodes)
obj->rotate(angle);
}
};
class Line: public IGraphic {
private:
static constexpr cstring _type = "Line";
std::string _id;
public:
Line(const std::string& id): _id{id} { }
auto type() const -> const std::string override {
return _type;
}
auto draw() -> void override {
std::cout << " [TRACE] Draw line - id = " << _id << "\n";
}
auto rotate(double angle) -> void override {
std::cout << " [TRACE] Rotate line ; id = " << _id
<< "; angle = " << angle << "\n";
}
};
class Triangle: public IGraphic {
private:
static constexpr cstring _type = "Triangle";
std::string _id;
public:
Triangle(const std::string& id): _id{id} { }
auto type() const -> const std::string override {
return _type;
}
auto draw() -> void override {
std::cout << " [TRACE] Draw triangle - id = " << _id << "\n";
}
auto rotate(double angle) -> void override {
std::cout << " [TRACE] Rotate triangle"
<< " id = " << _id
<< " angle = " << angle << "\n";
}
};
// Count total number of elements
auto countElements(const Group& group) -> size_t {
size_t n = 0;
for(const auto& g: group){
if(g->type() == "Group"){
auto p = static_cast<Group*>(g.get());
n += countElements(*p);
} else{ ++n; }
}
return n;
}
int main(){
const char nl = '\n';
std::cout << "=== Objects construction === " << nl;
auto groupA = Group("groupA");
groupA.add(new Triangle("triangleA1"));
groupA.add(new Line("lineA1"));
groupA.addNew<Line>("LineA2");
auto groupB = std::make_shared<Group>("GroupB");
groupB->add(new Triangle("triangleB1"));
groupB->addNew<Triangle>("triangleB2");
groupB->addNew<Line>("LineB1");
groupB->addNew<Line>("LineB2");
auto triangleB3 = Triangle("triangleB3");
groupB->addFromStack(&triangleB3);
groupA.add(groupB);
std::cout << nl << "=== End of object construction === " << nl;
std::cout << "Total of elements of groupA = " << countElements(groupA) << "\n";
std::cout << "Total of elements of groupB = " << countElements(*groupB) << "\n";
std::cout << nl << " [*] ==> Draw group B" << "\n";
groupB->draw();
std::cout << nl << " [*] ==> Rotate group B" << "\n";
groupB->rotate(90);
std::cout << nl << " [*] ==> Draw group A" << "\n";
groupA.draw();
std::cout << nl << " [*] ==> Rotate group A" << "\n";
groupA.rotate(15);
std::cout << nl << " [*] ==> Remove objects from group B" << "\n";
groupB->clear();
groupA.draw();
std::cout << "=== End of Program ====" << "\n";
return 0;
}