Skip to content

Commit 96ed5e2

Browse files
xiao chengxiao cheng
xiao cheng
authored and
xiao cheng
committed
bridge and composite pattern
1 parent e87e4e4 commit 96ed5e2

File tree

5 files changed

+341
-0
lines changed

5 files changed

+341
-0
lines changed

Bridge/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
3+
project(Bridge_test)
4+
5+
include_directories(${Boost_INCLUDE_DIRS})
6+
7+
add_executable(${PROJECT_NAME} bridgeTest.cpp)
8+
9+
target_link_libraries(${PROJECT_NAME} PUBLIC
10+
gtest_main
11+
${Boost_LIBRARIES}
12+
)
13+
14+
add_test(
15+
NAME ${PROJECT_NAME}
16+
COMMAND ${PROJECT_NAME}
17+
)
18+
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ../bin)

Bridge/bridgeTest.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <sstream>
4+
5+
using namespace std;
6+
7+
struct Renderer
8+
{
9+
virtual string what_to_render_as() const = 0;
10+
};
11+
12+
struct Shape
13+
{
14+
string name;
15+
const Renderer &renderer;
16+
17+
Shape(const Renderer &renderer) : renderer{renderer}
18+
{
19+
}
20+
21+
string str() const
22+
{
23+
ostringstream oss;
24+
oss << "Drawing " << name << " as "
25+
<< renderer.what_to_render_as();
26+
return oss.str();
27+
}
28+
};
29+
30+
struct Triangle : Shape
31+
{
32+
explicit Triangle(const Renderer &renderer)
33+
: Shape{renderer}
34+
{
35+
name = "Triangle";
36+
}
37+
};
38+
39+
struct Square : Shape
40+
{
41+
explicit Square(const Renderer &renderer)
42+
: Shape{renderer}
43+
{
44+
name = "Square";
45+
}
46+
};
47+
48+
struct RasterRenderer : Renderer
49+
{
50+
string what_to_render_as() const override
51+
{
52+
return "pixels";
53+
}
54+
};
55+
56+
struct VectorRenderer : Renderer
57+
{
58+
string what_to_render_as() const override
59+
{
60+
return "lines";
61+
}
62+
};
63+
64+
#include "gtest/gtest.h"
65+
66+
namespace
67+
{
68+
class Evaluate : public testing::Test
69+
{
70+
};
71+
72+
TEST_F(Evaluate, SimpleTest)
73+
{
74+
ASSERT_EQ("Drawing Square as lines", Square{VectorRenderer{}}.str());
75+
}
76+
} // namespace
77+
78+
int main(int ac, char *av[])
79+
{
80+
testing::InitGoogleTest(&ac, av);
81+
return RUN_ALL_TESTS();
82+
}

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ if(Boost_FOUND)
2121
add_subdirectory(RAII)
2222
add_subdirectory(Decorator)
2323
add_subdirectory(Adaptor)
24+
add_subdirectory(Bridge)
25+
add_subdirectory(Composite)
2426
endif()

Composite/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
3+
project(Composite_test)
4+
5+
include_directories(${Boost_INCLUDE_DIRS})
6+
7+
add_executable(${PROJECT_NAME} compositeTest.cpp)
8+
9+
target_link_libraries(${PROJECT_NAME} PUBLIC
10+
gtest_main
11+
${Boost_LIBRARIES}
12+
)
13+
14+
add_test(
15+
NAME ${PROJECT_NAME}
16+
COMMAND ${PROJECT_NAME}
17+
)
18+
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ../bin)

Composite/compositeTest.cpp

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
#include <memory>
2+
#include <vector>
3+
#include <deque>
4+
#include <string>
5+
#include <iostream>
6+
7+
class IGraphic
8+
{
9+
public:
10+
virtual auto type() const -> const std::string = 0;
11+
virtual auto draw() -> void = 0;
12+
virtual auto rotate(double) -> void = 0;
13+
virtual ~IGraphic() = default;
14+
};
15+
16+
using cstring = const char *;
17+
using GNode = std::shared_ptr<IGraphic>;
18+
19+
class Group : public IGraphic
20+
{
21+
private:
22+
std::vector<GNode> _nodes;
23+
std::string _id;
24+
static constexpr cstring _type = "Group";
25+
26+
public:
27+
Group(const std::string &id) : _id(id)
28+
{
29+
std::cout << " [TRACE] Create group = " << id << "\n";
30+
}
31+
~Group()
32+
{
33+
std::cout << " [TRACE] Destroy group - id = << " << _id << "\n";
34+
}
35+
36+
auto begin() const -> decltype(_nodes.begin())
37+
{
38+
return _nodes.begin();
39+
}
40+
auto end() const -> decltype(_nodes.end())
41+
{
42+
return _nodes.end();
43+
}
44+
45+
auto clear() -> void
46+
{
47+
_nodes.clear();
48+
}
49+
auto size() -> size_t
50+
{
51+
return _nodes.size();
52+
}
53+
auto add(GNode n) -> void
54+
{
55+
std::cout << " [TRACE] id = " << _id
56+
<< "; Add object = " << n->type() << "\n";
57+
_nodes.push_back(n);
58+
}
59+
auto add(IGraphic *n) -> void
60+
{
61+
std::cout << " [TRACE] id = " << _id
62+
<< " ; Add object = " << n->type() << "\n";
63+
_nodes.push_back(std::shared_ptr<IGraphic>(n));
64+
}
65+
// Add stack-allocated object
66+
auto addFromStack(IGraphic *n) -> void
67+
{
68+
std::cout << " [TRACE] id = " << _id
69+
<< " ; Add object = " << n->type() << "\n";
70+
// Dummy deleter to avoid core dump by avoiding deleting
71+
// stack-allocated object or non-owned pointer.
72+
auto s = std::shared_ptr<IGraphic>(n, [](IGraphic *) { return; });
73+
_nodes.push_back(s);
74+
}
75+
76+
// Note: Template methods should always be in the header files
77+
template <class Node>
78+
auto addNew(const std::string &id) -> void
79+
{
80+
auto n = std::make_unique<Node>(id);
81+
std::cout << " [TRACE] id = " << _id
82+
<< " ; Add object = " << n->type() << "\n";
83+
_nodes.push_back(std::move(n));
84+
}
85+
86+
// ======> Interface IGraphic <<=========//
87+
88+
auto type() const -> const std::string override
89+
{
90+
return _type;
91+
}
92+
auto draw() -> void override
93+
{
94+
std::cout << " [TRACE] Draw group - id = " << _id << "\n";
95+
for (const auto &obj : _nodes)
96+
obj->draw();
97+
}
98+
auto rotate(double angle) -> void override
99+
{
100+
std::cout << " [TRACE] Rotate group - id = " << _id << "\n";
101+
for (const auto &obj : _nodes)
102+
obj->rotate(angle);
103+
}
104+
};
105+
106+
class Line : public IGraphic
107+
{
108+
private:
109+
static constexpr cstring _type = "Line";
110+
std::string _id;
111+
112+
public:
113+
Line(const std::string &id) : _id{id} {}
114+
auto type() const -> const std::string override
115+
{
116+
return _type;
117+
}
118+
auto draw() -> void override
119+
{
120+
std::cout << " [TRACE] Draw line - id = " << _id << "\n";
121+
}
122+
auto rotate(double angle) -> void override
123+
{
124+
std::cout << " [TRACE] Rotate line ; id = " << _id
125+
<< "; angle = " << angle << "\n";
126+
}
127+
};
128+
129+
class Triangle : public IGraphic
130+
{
131+
private:
132+
static constexpr cstring _type = "Triangle";
133+
std::string _id;
134+
135+
public:
136+
Triangle(const std::string &id) : _id{id} {}
137+
auto type() const -> const std::string override
138+
{
139+
return _type;
140+
}
141+
auto draw() -> void override
142+
{
143+
std::cout << " [TRACE] Draw triangle - id = " << _id << "\n";
144+
}
145+
auto rotate(double angle) -> void override
146+
{
147+
std::cout << " [TRACE] Rotate triangle"
148+
<< " id = " << _id
149+
<< " angle = " << angle << "\n";
150+
}
151+
};
152+
153+
// Count total number of elements
154+
auto countElements(const Group &group) -> size_t
155+
{
156+
size_t n = 0;
157+
for (const auto &g : group)
158+
{
159+
if (g->type() == "Group")
160+
{
161+
auto p = static_cast<Group *>(g.get());
162+
n += countElements(*p);
163+
}
164+
else
165+
{
166+
++n;
167+
}
168+
}
169+
return n;
170+
}
171+
172+
int main()
173+
{
174+
const char nl = '\n';
175+
176+
std::cout << "=== Objects construction === " << nl;
177+
178+
auto groupA = Group("groupA");
179+
groupA.add(new Triangle("triangleA1"));
180+
groupA.add(new Line("lineA1"));
181+
groupA.addNew<Line>("LineA2");
182+
183+
auto groupB = std::make_shared<Group>("GroupB");
184+
groupB->add(new Triangle("triangleB1"));
185+
groupB->addNew<Triangle>("triangleB2");
186+
groupB->addNew<Line>("LineB1");
187+
groupB->addNew<Line>("LineB2");
188+
auto triangleB3 = Triangle("triangleB3");
189+
groupB->addFromStack(&triangleB3);
190+
groupA.add(groupB);
191+
192+
std::cout << nl << "=== End of object construction === " << nl;
193+
std::cout << "Total of elements of groupA = " << countElements(groupA) << "\n";
194+
std::cout << "Total of elements of groupB = " << countElements(*groupB) << "\n";
195+
196+
std::cout << nl << " [*] ==> Draw group B"
197+
<< "\n";
198+
groupB->draw();
199+
200+
std::cout << nl << " [*] ==> Rotate group B"
201+
<< "\n";
202+
groupB->rotate(90);
203+
204+
std::cout << nl << " [*] ==> Draw group A"
205+
<< "\n";
206+
groupA.draw();
207+
208+
std::cout << nl << " [*] ==> Rotate group A"
209+
<< "\n";
210+
groupA.rotate(15);
211+
212+
std::cout << nl << " [*] ==> Remove objects from group B"
213+
<< "\n";
214+
groupB->clear();
215+
groupA.draw();
216+
217+
std::cout << "=== End of Program ===="
218+
<< "\n";
219+
220+
return 0;
221+
}

0 commit comments

Comments
 (0)