// Composite
// - Compose objects into tree structures to represent part-whole
// hierarchies. Composite lets client treat individual objects and
// compositons of objects uniformly.
//
// Author : ZAsia
// Date : 15/05/09
// Warning : In practice, declaration and implementation should
// be separated(.h and .cpp).
#include
#include
using namespace std;
// Component
// - declares the interface for objects in the composition
// - implements default behavior for the interface common to all
// classes, as appropriate.
// - declares an interface for accessing and managing its child components.
// - (optional) defines an interface for accessing a component's parent in
// the recursive structure, and implements it if that's appropriate.
class Component
{
public:
Component(const char *name) : _name(name) { }
// The destructor needs to be virtual to allow objects
// in the heritance hierarchy to be dynamically allocated.
virtual ~Component() { }
const char *Name() { return _name; }
virtual void Operation() = 0;
virtual void Add(Component *com) { }
virtual void Remove(Component *com) { }
virtual Component *GetChild(unsigned int) { return nullptr; }
private:
const char *_name;
};
// Leaf
// - represents leaf objects in the composition. A leaf has no children.
// - defines behavior for primitive objects in the compositon.
class Leaf : public Component
{
public:
Leaf(const char *name) : Component(name) { }
~Leaf() { cout << "delet " << Name() << endl; }
virtual void Operation() { cout << "I'm " << Name() << endl; }
};
// Composite
// - defines behavior for components haveing children
// - stores child components
// - implements chile-related operations in the Component interface
class Composite : public Component
{
public:
Composite(const char *name) : Component(name) { }
~Composite()
{
cout << "delet " << Name() << endl;
for (vector
::iterator iter = vecComponent.begin();
iter != vecComponent.end(); iter = vecComponent.begin())
{
delete *iter;
vecComponent.erase(iter);
}
}
virtual void Operation()
{
cout << "I'm " << Name() << " , now children introduce yourself:" << endl;
for (vector
::iterator iter = vecComponent.begin();
iter != vecComponent.end(); ++iter)
{
(*iter)->Operation();
}
}
virtual void Add(Component *com)
{
vecComponent.push_back(com);
}
virtual void Remove(Component *com)
{
for (vector
::iterator iter = vecComponent.begin(); iter != vecComponent.end(); ++iter) { if (strcmp((*iter)->Name(), com->Name()) == 0) { delete *iter; vecComponent.erase(iter); break; } } } virtual Component *GetChild(unsigned int index) { if (index >= vecComponent.size()) { return nullptr; } return vecComponent[index]; } private: vector
vecComponent; }; // Client // - manipulates objects in the composition through the Component interface // // Collaborations // - Clients use the Component class interface to interact with objects in the // composite structure. If the recipient is a Leaf, then the request is handled // directly. If the recipient is a Composite, then it usually forwards requests // to its child components, possibly performing additional operations before // and/or after forwarding. int main() { // Composite Component *pComposite = new Composite("Suzhou Head Office"); // Add ChildLeaf pComposite->Add(new Leaf("Suzhou Human Resource Department")); pComposite->Add(new Leaf("Suzhou Research and Development Department")); // Add ChildComposite pComposite->Add(new Composite("Beijing Branch")); // Add Leaf to ChildComposite pComposite->GetChild(2)->Add(new Leaf("Beijing Human Resource Department")); pComposite->GetChild(2)->Add(new Leaf("Beijing Research and Development Department")); // Operation pComposite->Operation(); pComposite->GetChild(2)->Operation(); // Close Beijing Branch pComposite->Remove(pComposite->GetChild(2)); // Close Suzhou Head Office if (pComposite != nullptr) { delete pComposite; pComposite = nullptr; } return 0; } // 1. defines class hierarchies consisting of primitive objects and composite // objects. Primitive objects can be composed into more complex objects, // which in turn can be composed, and so on recursively. Wherever client // code expects primitive object, it can also take a composite object. // 2. Who should delete components? In language without garbage collection, // it's usually best to make a Composite responsible for deleting its // children when it's destroyed.