Skip to content

Commit b4575f8

Browse files
authored
Merge pull request #14 from urboob21/dev_branch
id 1763290812
2 parents 1e45aee + 33ccdaf commit b4575f8

5 files changed

Lines changed: 236 additions & 3 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ set(APP_SOURCES
9797
"src/patterns/structural/Composite.cpp"
9898
"src/patterns/structural/Flyweight.cpp"
9999
"src/patterns/structural/Facade.cpp"
100+
"src/patterns/structural/Decorator.cpp"
100101
)
101102

102103
# Test files

docs/uml/patterns_structural_decorator.drawio.svg

Lines changed: 4 additions & 0 deletions
Loading

src/patterns/structural/Composite.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Appicability:
55
// (*) when you have to implement a tree-like object structure.
66
// (**) when you want the client code to treat both simple and complex elements uniformly.
7-
// UML: docs/uml/patterns_structural_facade.drawio.svg
7+
// UML: docs/uml/patterns_structural_composite.drawio.svg
88

99
#include <iostream>
1010
#include <string>
@@ -534,7 +534,7 @@ struct CompositeAutoRuner
534534
CompositeAutoRuner()
535535
{
536536
std::cout << "\n--- Composite Pattern Example ---\n";
537-
// Problem::run();
537+
Problem::run();
538538
CompositePattern::run();
539539
}
540540
};
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
// Decorator is a structural design pattern that lets you attach new behaviors to objects
2+
// by placing these objects inside special wrapper objects that contain the behaviors.
3+
// Appicability:
4+
// (*) when you need to be able to assign extra behaviors to objects at runtime without breaking the code that uses these objects.
5+
// (**) when it’s awkward or not possible to extend an object’s behavior using inheritance.
6+
// UML: docs/uml/patterns_structural_decorator.drawio.svg
7+
8+
#include <iostream>
9+
#include <string>
10+
#include <list>
11+
#include <algorithm>
12+
13+
namespace
14+
{
15+
namespace Problem
16+
{
17+
18+
class IComponent
19+
{
20+
public:
21+
virtual ~IComponent() {}
22+
virtual std::string operation() const = 0;
23+
};
24+
25+
class ConcreteComponent : public IComponent
26+
{
27+
public:
28+
std::string operation() const override
29+
{
30+
return "ConcreteComponent";
31+
}
32+
};
33+
34+
class ComponentWithA : public ConcreteComponent
35+
{
36+
public:
37+
std::string operation() const override
38+
{
39+
return ConcreteComponent::operation() + " + FeatureA";
40+
}
41+
};
42+
43+
class ComponentWithB : public ConcreteComponent
44+
{
45+
public:
46+
std::string operation() const override
47+
{
48+
return ConcreteComponent::operation() + " + FeatureB";
49+
}
50+
};
51+
52+
class ComponentWithAandB : public ConcreteComponent
53+
{
54+
public:
55+
std::string operation() const override
56+
{
57+
return ConcreteComponent::operation() + " + FeatureA + FeatureB";
58+
}
59+
};
60+
61+
// [P1]
62+
// If you have 3 features , e.g FeatureC -> many combinations
63+
// If you have 5 features -> 32 subclasses
64+
65+
namespace Client
66+
{
67+
void clientCode(const IComponent &comp)
68+
{
69+
std::cout << comp.operation() << "\n";
70+
}
71+
}
72+
73+
void run()
74+
{
75+
std::cout << "\n\nProblem\n";
76+
IComponent *simple = new ConcreteComponent;
77+
Client::clientCode(*simple);
78+
79+
IComponent *withA = new ComponentWithA;
80+
Client::clientCode(*withA);
81+
82+
IComponent *withB = new ComponentWithB;
83+
Client::clientCode(*withB);
84+
85+
IComponent *withAB = new ComponentWithAandB;
86+
Client::clientCode(*withAB);
87+
88+
delete simple;
89+
delete withA;
90+
delete withB;
91+
delete withAB;
92+
}
93+
94+
}
95+
96+
namespace DecoratorPattern
97+
{
98+
class IComponent
99+
{
100+
public:
101+
virtual ~IComponent() {}
102+
virtual std::string operation() const = 0;
103+
};
104+
105+
/**
106+
* Concrete Component
107+
* - is a class of objects being wrapped.
108+
* - defines the basic behavior, which can be altered by decorators.
109+
*/
110+
class ConcreteComponent : public IComponent
111+
{
112+
public:
113+
std::string operation() const override
114+
{
115+
return "ConcreteComponent";
116+
}
117+
};
118+
119+
/**
120+
* The base Decorator class follows the same interface as the other components.
121+
* - has a field for referencing a wrapped object.
122+
* - the field’s type should be declared as the component interface so it can contain both concrete components and decorators.
123+
* - the base decorator delegates all operations to the wrapped object.
124+
*/
125+
class BaseDecorator : public IComponent
126+
{
127+
protected:
128+
IComponent *m_component;
129+
130+
public:
131+
explicit BaseDecorator(IComponent *component) : m_component{component} {}
132+
133+
/**
134+
* The Decorator delegates all work to the wrapped component.
135+
*/
136+
std::string operation() const override
137+
{
138+
return m_component->operation();
139+
}
140+
};
141+
142+
/**
143+
* Concrete Decorators :
144+
* - call the wrapped object and alter its result in some way.
145+
* - define extra behaviors that can be added to components dynamically.
146+
* - override methods of the base decorator and execute their behavior either before
147+
* or after calling the parent method.
148+
*/
149+
class ConcreteDecoratorA : public BaseDecorator
150+
{
151+
public:
152+
explicit ConcreteDecoratorA(IComponent *component) : BaseDecorator{component} {}
153+
154+
std::string operation() const override
155+
{
156+
return BaseDecorator::operation() + " + FeatureA";
157+
}
158+
};
159+
160+
class ConcreteDecoratorB : public BaseDecorator
161+
{
162+
public:
163+
explicit ConcreteDecoratorB(IComponent *component) : BaseDecorator{component} {}
164+
165+
std::string operation() const override
166+
{
167+
return BaseDecorator::operation() + " + FeatureB";
168+
}
169+
};
170+
171+
class ConcreteDecoratorC : public BaseDecorator
172+
{
173+
public:
174+
explicit ConcreteDecoratorC(IComponent *component) : BaseDecorator{component} {}
175+
176+
std::string operation() const override
177+
{
178+
return BaseDecorator::operation() + " + FeatureC";
179+
}
180+
};
181+
182+
namespace Client
183+
{
184+
void clientCode(const IComponent &comp)
185+
{
186+
std::cout << comp.operation() << "\n";
187+
}
188+
}
189+
190+
void run()
191+
{
192+
std::cout << "\n\nDecorator\n";
193+
IComponent *simple = new ConcreteComponent;
194+
Client::clientCode(*simple);
195+
196+
IComponent *withA = new ConcreteDecoratorA(simple);
197+
Client::clientCode(*withA);
198+
199+
IComponent *withB = new ConcreteDecoratorB(simple);
200+
Client::clientCode(*withB);
201+
202+
IComponent *withAB = new ConcreteDecoratorB(withA);
203+
Client::clientCode(*withAB);
204+
205+
IComponent *withABC = new ConcreteDecoratorC(withAB);
206+
Client::clientCode(*withABC);
207+
208+
delete simple;
209+
delete withA;
210+
delete withB;
211+
delete withAB;
212+
delete withABC;
213+
}
214+
}
215+
216+
}
217+
218+
struct DecoratorAutoRuner
219+
{
220+
DecoratorAutoRuner()
221+
{
222+
std::cout << "\n--- Decorator Pattern Example ---\n";
223+
Problem::run();
224+
DecoratorPattern::run();
225+
}
226+
};
227+
228+
static DecoratorAutoRuner instance;

src/patterns/structural/Facade.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Appicability:
66
// (*) when you need to have a limited but straightforward interface to a complex subsystem.
77
// (**) when you want to structure a subsystem into layers.
8-
// UML: none
8+
// UML: docs/uml/patterns_structural_facade.drawio.svg
99

1010
#include <iostream>
1111
namespace

0 commit comments

Comments
 (0)