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 see my web
site. You can also
join Design
pattern and concepts in
Facebook or Design
for future in google+. Drop
comments for any question related to this blog.