Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. The frequency of use of this is medium high.
The Intent of the 'Composite Pattern' is:
- Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
- Recursive composition
- “Directories contain entries, each of which could be a directory.”
- 1-to-many “has a” up the “is a” hierarchy
//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Composite is part of Structural Patterns
//Structural Patterns deal with decoupling the interface and implementation of classes and objects
//Composite pattern forms a tree structure of simple and composite objects
//The example here
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//The 'Component' Treenode
class DrawingElement
{
public:
DrawingElement(string name) : name_(name) {};
virtual void Add(DrawingElement* d) = 0;
virtual void Remove(DrawingElement* d) = 0;
virtual void Display(int indent) = 0;
virtual ~DrawingElement() {};
protected:
string name_;
private:
DrawingElement(); //not allowed
};
//The 'Leaf' class
class PrimitiveElement : public DrawingElement
{
public:
PrimitiveElement(string name) : DrawingElement(name){};
void Add(DrawingElement* d)
{
cout<<"Cannot add to a PrimitiveElement"<<endl;
}
void Remove(DrawingElement* d)
{
cout<<"Cannot remove from a PrimitiveElement"<<endl;
}
void Display(int indent)
{
string newStr(indent, '-');
cout << newStr << " " << name_ <<endl;
}
virtual ~PrimitiveElement(){};
private:
PrimitiveElement(); //not allowed
};
//The 'Composite' class
class CompositeElement : public DrawingElement
{
public:
CompositeElement(string name) : DrawingElement(name) {};
void Add(DrawingElement* d)
{
elements_.push_back(d);
}
void Remove(DrawingElement* d)
{
vector<DrawingElement*>::iterator it = elements_.begin();
while(it != elements_.end())
{
if(*it == d)
{
delete d;
elements_.erase(it);
break;
}
++it;
}
}
void Display(int indent)
{
string newStr(indent, '-');
cout << newStr << "+ " << name_ <<endl;
vector<DrawingElement*>::iterator it = elements_.begin();
while(it != elements_.end())
{
(*it)->Display(indent + 2);
++it;
}
}
virtual ~CompositeElement()
{
while(!elements_.empty())
{
vector<DrawingElement*>::iterator it = elements_.begin();
delete *it;
elements_.erase(it);
}
}
private:
CompositeElement(); //not allowed
vector<DrawingElement*> elements_;
};
//The Main method
int main()
{
//Create a Tree Structure
CompositeElement* root = new CompositeElement("Picture");
root->Add(new PrimitiveElement("Red Line"));
root->Add(new PrimitiveElement("Blue Circle"));
root->Add(new PrimitiveElement("Green Box"));
//Create a Branch
CompositeElement* comp = new CompositeElement("Two Circles");
comp->Add(new PrimitiveElement("Black Circle"));
comp->Add(new PrimitiveElement("White Circle"));
root->Add(comp);
//Add and remove a primitive elements
PrimitiveElement* pe1 = new PrimitiveElement("Yellow Line");
root->Add(pe1);
PrimitiveElement* pe2 = new PrimitiveElement("Orange Triangle");
root->Add(pe2);
root->Remove(pe1);
//Recursively display nodes
root->Display(1);
//delete the allocated memory
delete root;
return 0;
}
The output is as follows:
For more information see: