Composite Design Pattern in C++

Prerequisite : Composite Design Pattern

Composite pattern is one of the most widely used patterns in the industry and addresses a very significant and subtle problem. It is used whenever the user wants to treat the individual object in the same way as the collection of those individual objects for e.g you might want to consider a page from the copy as same as the whole copy which is basically a collection of the pages or if you want to create a hierarchy of something where you might want to consider the whole thing as the object . 

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

In the case of photoshop where we draw many individual objects and then those objects compose a whole unique object and you might want to apply some operation on the whole object instead of the each of the individual objects. 
 


Here in this diagram, as you can see both composite and Leaf implements Component diagram, thus allowing the same operation on both objects but the important part is Composite Class which also contain the Component Objects which is symbolized by the black diamond indicating composition relationship between Composite and Component class.

Then how to design our classes to accommodate such scenarios. We will try to understand it by implementing our copy example. Say you have to create a page which has operations like add, delete, remove and also a copy which will have the same operations as the individual pages.
Such situation is the best dealt with the composite pattern. 
 

CPP
// CPP program to illustrate
// Composite design pattern
#include <iostream>
#include <vector>
using namespace std;

class PageObject {
public:
    virtual void Add(PageObject a) {}
    virtual void Remove() {}
    virtual void Delete(PageObject a) {}
};

class Page : public PageObject {
public:
    void Add(PageObject a)
    {
        cout << "something is added to the page" << endl;
    }
    void Remove()
    {
        cout << "something is removed from the page"
             << endl;
    }
    void Delete(PageObject a)
    {
        cout << "something is deleted from page " << endl;
    }
};

class Copy : public PageObject {
    vector<PageObject> copyPages;

public:
    void AddElement(PageObject a)
    {
        copyPages.push_back(a);
    }

    void Add(PageObject a)
    {
        cout << "something is added to the copy" << endl;
    }
    void Remove()
    {
        cout << "something is removed from the copy"
             << endl;
    }
    void Delete(PageObject a)
    {
        cout << "something is deleted from the copy";
    }
};

int main()
{
    Page a;
    Page b;
    Copy allcopy;
    allcopy.AddElement(a);
    allcopy.AddElement(b);

    allcopy.Add(a);
    a.Add(b);

    allcopy.Remove();
    b.Remove();

    return 0;
}

Output
something is added to the copy
something is added to the page
something is removed from the copy
something is removed from the page

Time complexity : O(1)
Auxiliary Space : O(1)

Now the same operation that can be applied to an individual object and can also be applied to the collection of those individual object makes it very easy to work with a larger object which is made of the smaller independent objects.

The most notable example of the composite pattern is in any UI toolkit. Consider the case of UI elements where each UI top-level UI element is composed of many smaller independent lower-level UI elements and the both the top and lower level UI element respond to same events and actions.

References : 

  1. Composite Pattern c# 
  2. Composite Pattern


     


Contact Us