Skip to content

Commit b7feac6

Browse files
committed
[COMPOSITE]: Added ressources and sample code for Composite pattern.
1 parent 0643c2a commit b7feac6

File tree

3 files changed

+170
-2
lines changed

3 files changed

+170
-2
lines changed
Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,57 @@
1-
# TODO
1+
# Intend
22

3-
Stay tuned, this section will be completed shortly !
3+
**Compose objects** into tree structures to represent part-whole hierarchies.
4+
5+
It **lets clients treat individual objects and compositions uniformly**.
6+
7+
You should use the _Composite_ pattern in the following cases :
8+
- The core model of your app can be **represented as a tree**.
9+
- You want (or you want the Client) to perform operations on composite objects as if they were standard objects - that is interacting with them using a **common interface**.
10+
11+
# How it's done
12+
13+
![UML](UML.jpg)
14+
15+
**Participants**
16+
17+
- _Component_ :
18+
- Declares the **interface** for the objects in the composition.
19+
- Implements the **default behaviour** for the **common interface** to all classes.
20+
- Declares an **interface** for **managing childs components**.
21+
- _Leaf_ :
22+
- An object of the composition that has no children.
23+
- Defines the **default behaviour** of **primitive objects**.
24+
- _Composite_ :
25+
- Defines behaviour for components having children.
26+
- **Stores** the child components.
27+
- Implements the **child-related operations** in the _Component_ interface.
28+
- _Client_ : Manipulates the objects in the composition through the _Component_ interface.
29+
30+
**How to implement**
31+
32+
1. **Make sure** the model of your app can be represented as a Tree.
33+
2. **Declare** the _Component_ interface with the methods that make sense for both _Leafs_ and _Composites_.
34+
3. **Create** _Leaf_ classes to represent simple elements that do not have children.
35+
4. **Create** _Composite_ classes with an underlying container for children, methods to add/remove children.
36+
5. **Implement** the _Component_ methods in the _Composite_ delegating the hard work to children.
37+
38+
Note : UML class diagram taken from [**here**](https://upload.wikimedia.org/wikipedia/commons/3/39/W3sDesign_Composite_Design_Pattern_Type_Safety_UML.jpg)
39+
40+
# Pros & cons
41+
42+
**Pros**
43+
44+
- You and your clients can work easily with complex structures.
45+
- **Open/Closed principle**: It is easy to introduce new elements in the apps without breaking the existing code.
46+
- Reduce code complexity by eliminating many loops over the homogeneous collection of objects.
47+
48+
**Cons**
49+
50+
- It might be difficult to provide a common interface for classes whose functionality differs too much. In certain scenarios, you’d need to overgeneralize the component interface, making it harder to comprehend.
51+
52+
# Notes
53+
54+
Here are some _usefull ressources_ :
55+
- A great article on [**Source making**](https://sourcemaking.com/design_patterns/composite)
56+
- A [**blog article**](http://www.vishalchovatiya.com/composite-design-pattern-in-modern-cpp/) showing an example using [**CRTP**](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
57+
- A [**Refactoring guru**](https://refactoring.guru/design-patterns/composite) article.

structural-patterns/composite/UML.jpg

43.7 KB
Loading
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*!
2+
* @brief : This example was originally declared in "Desgin Patterns :
3+
* Elements of reusable Object-oriented software".
4+
*/
5+
6+
#include <vector>
7+
#include <iostream>
8+
#include <algorithm>
9+
#include <functional>
10+
11+
// ------- COMPONENT ------- //
12+
/*!
13+
* @brief Component - declares the common interface for every
14+
* objects (Leaf or Composite) of the composition.
15+
*/
16+
class Graphic {
17+
public:
18+
virtual ~Graphic() = default;
19+
20+
virtual void draw (void) const = 0; // An operation method
21+
virtual bool isComposite(void) const { return false; }
22+
23+
virtual void setParent(Graphic* p_parent) { m_parent = p_parent; }
24+
virtual Graphic* getParent(void) const { return m_parent; }
25+
26+
/*!
27+
* Note : These are child-management operations.
28+
* Defining them in the Component class ensure you that you
29+
* will not need to expose any Leaf/Composite to the client code.
30+
*/
31+
virtual void remove (Graphic *g) { /* EMPTY */ }
32+
virtual void add (Graphic *g) { /* EMPTY */ }
33+
34+
protected:
35+
Graphic* m_parent;
36+
};
37+
38+
// --------- LEAFS --------- //
39+
/*!
40+
* @brief Leafs - Leaf objects of the composition.
41+
* - They have no children.
42+
* - They define the behaviour of the primitive objects.
43+
*/
44+
class Line : public Graphic {
45+
public:
46+
void draw(void) const override { std::cout << "Line\n"; }
47+
};
48+
49+
class Rectangle : public Graphic {
50+
public:
51+
void draw(void) const override { std::cout << "Rectangle\n"; }
52+
};
53+
54+
class Text : public Graphic {
55+
public:
56+
void draw(void) const override { std::cout << "Text\n"; }
57+
};
58+
59+
60+
// --------- COMPOSITE --------- //
61+
/*!
62+
* @brief Composite - Composite objects
63+
* - Stores children (Leaf or Composite)
64+
* - Implement the Component interface for
65+
* the child-related operations
66+
*/
67+
class Picture : public Graphic {
68+
public:
69+
Picture(std::string&& p_name = ""): m_name(p_name) {}
70+
virtual ~Picture() = default;
71+
72+
virtual bool isComposite(void) const override { return true; }
73+
74+
void draw(void) const override {
75+
std::for_each( std::begin(m_sons),
76+
std::end (m_sons),
77+
[](Graphic* it){ it->draw(); } );
78+
}
79+
80+
void add (Graphic* p_elem) { m_sons.push_back(p_elem); }
81+
void remove(Graphic* p_elem) {
82+
m_sons.erase(std::remove(std::begin(m_sons),
83+
std::end (m_sons),
84+
p_elem), std::end (m_sons));
85+
}
86+
87+
private:
88+
std::vector<Graphic*> m_sons;
89+
std::string m_name;
90+
91+
};
92+
93+
// --------- CLIENT CODE --------- //
94+
/*!
95+
* @brief : Client Code
96+
* Can work with Picture just as if
97+
* it was a Leaf.
98+
*/
99+
int main()
100+
{
101+
Line line; line.draw();
102+
Rectangle rect; rect.draw();
103+
Text text; text.draw();
104+
105+
std::cout << std::endl;
106+
107+
Picture pic;
108+
pic.add(&line);
109+
pic.add(&rect);
110+
pic.add(&text);
111+
pic.draw();
112+
113+
return 0;
114+
}

0 commit comments

Comments
 (0)