Composite design pattern.
Background –
Before we jump into composite design pattern first let’s focus on whole-part relationship.
What is whole-part relationship?
When an object contains (or holds) another object in it, we say it is a whole-part relationship.
types of whole-part relationship –
There are two kind of whole-pert relationship –
a. Composition
b. Aggregation
Composition –
If you destroy whole part will also gets destroyed. Or if you delete whole object part object will be deleted.
For example –
There is a single room constructed by 4 walls like it is mentioned at below image. If we blast or destroy room all 4 walls will be destroyed.
Aggregation –
Destroying whole will not destroy part. Or deleting whole object will not delete part object.
For example –
Consider 2 rooms with 7 walls where 1 wall is common among them same as mentioned at below. Now if I destroy room 1, room 2 is still in existence.
Even I have destroyed whole; part (which was now shared between two objects) is still alive. It means in aggregation two whole objects share same part object.
UML notation for whole-part relations -
class A is whole and class B is part.
Composite design pattern –
I am hoping that we have got basic idea of whole-part relationship. Composite design pattern says whenever you see any requirement where we have no difference on how we are operating on whole and part & the structure of problem is nested till any levels (form a tree structure) use composite.
Let us understand it in very simple way through a classical example –
1. Zip –
Requirement says we have a file system. Where you may want to zip a file or a folder which contains many other folders and files in it.
Now let’s understand it –
a. One thing is very clear folder is whole and file is part. As folder contain files.
b. Operation wise there is no difference between folder (whole) and file (part). We need to zip both.
c. There will be a starting point. For example zip folder X. folder X will be the starting of zip and it may contain other files or folders inside it; which will create tree a structure.
So from the requirements we understood that we have a tree structure and whole-part relation which is a clear candidate of composite design pattern.
2. UI navigation-
One of the most commonly told example is UI development scenarios. Where we have a main label from where it may show some list of options and after moving the mouse cursor it may show many more options and at the end you will have final link.
More specifically –
You go to any educational website, you may see 2 options there – UG & PG.
- After you click UG it may show some more options – engineering, pharmacy, BCA
- After you click engineering, it may show you – IT,CS,EC,EEE
- After you move cursor to IT it will actually give you a final link to go to IT branch and see specific content.
If you analyze the problem it is very similar to what we have learnt here.
1. There is a whole part relationship; label will contain another label or final link.
2. There is no guarantee how many labels will be there; it is depends upon requirement and client.
3. Any flow has to start from some root (here UG or PG) and form a tree structure.
you can select any flow it will form a tree structure, but there is no fixed length, it can go to any nested levels.
Structure -
The key to the composite pattern is the interface (or component) which represents whole as well as part.
Example -
C++ Code -
//////////////////////////////////////////////////////////////////////////////// //C++ code to understand composite design pattern. // // ////////////////////////////////////////////////////////////////////////////////#include <iostream> #include <vector> using namespace std; // Create an "interface" class Component { public: virtual void show() = 0; }; // This is a class which has actual information. class Leaf: public Component { // for example take an integer. int value; public: Leaf(int val) { value = val; } void show() { cout << value << ' '<<endl; } }; class Composite: public Component { // 1. Vector class , as I mentioned it can go till any nested level we can add them in vector. vector < Component * > children; // 4. "container" public: void add(Component *ele) { children.push_back(ele); } void show() { for (int i = 0; i < children.size(); i++) // 5. Use polymorphism to delegate to children children[i]->show(); } }; int main() { Composite containers[4]; for (int i = 0; i < 7; i++) for (int j = 0; j < 5; j++) containers[i].add(new Leaf(i *5+j)); for (i = 1; i < 7; i++) containers[0].add(&(containers[i])); for (i = 0; i < 7; i++) { containers[i].show(); cout << endl; } }
Thanks for reading it. To read more on design patterns and basic design principles please see my web page. You can also join me on FB or on G++. Please drop comments for any question related to this blog.
Comments
Post a Comment