Wednesday 15 September 2010

C++ example for Composite Design Pattern


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
C++ example as follows:



//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:

1 comment:

  1. It was not a safe way of building composite classes. We dont usually declare composite class functions in the base class. but good example in general. tnx

    ReplyDelete