#include<algorithm> #include<iostream> #include<list> #include<string> /** * The base Component class declares common operations for both simple and * complex objects of a composition. */ classComponent { /** * @var Component */ protected: Component *parent_; /** * Optionally, the base Component can declare an interface for setting and * accessing a parent of the component in a tree structure. It can also * provide some default implementation for these methods. */ public: virtual ~Component() {} voidSetParent(Component *parent){ this->parent_ = parent; } Component *GetParent()const{ returnthis->parent_; } /** * In some cases, it would be beneficial to define the child-management * operations right in the base Component class. This way, you won't need to * expose any concrete component classes to the client code, even during the * object tree assembly. The downside is that these methods will be empty for * the leaf-level components. */ virtualvoidAdd(Component *component){} virtualvoidRemove(Component *component){} /** * You can provide a method that lets the client code figure out whether a * component can bear children. */ virtualboolIsComposite()const{ returnfalse; } /** * The base Component may implement some default behavior or leave it to * concrete classes (by declaring the method containing the behavior as * "abstract"). */ virtual std::string Operation()const= 0; }; /** * The Leaf class represents the end objects of a composition. A leaf can't have * any children. * * Usually, it's the Leaf objects that do the actual work, whereas Composite * objects only delegate to their sub-components. */ classLeaf : public Component { public: std::string Operation()constoverride{ return"Leaf"; } }; /** * The Composite class represents the complex components that may have children. * Usually, the Composite objects delegate the actual work to their children and * then "sum-up" the result. */ classComposite : public Component { /** * @var \SplObjectStorage */ protected: std::list<Component *> children_;
public: /** * A composite object can add or remove other components (both simple or * complex) to or from its child list. */ voidAdd(Component *component)override{ this->children_.push_back(component); component->SetParent(this); } /** * Have in mind that this method removes the pointer to the list but doesn't * frees the * memory, you should do it manually or better use smart pointers. */ voidRemove(Component *component)override{ children_.remove(component); component->SetParent(nullptr); } boolIsComposite()constoverride{ returntrue; } /** * The Composite executes its primary logic in a particular way. It traverses * recursively through all its children, collecting and summing their results. * Since the composite's children pass these calls to their children and so * forth, the whole object tree is traversed as a result. */ std::string Operation()constoverride{ std::string result; for (const Component *c : children_) { if (c == children_.back()) { result += c->Operation(); } else { result += c->Operation() + "+"; } } return"Branch(" + result + ")"; } }; /** * The client code works with all of the components via the base interface. */ voidClientCode(Component *component){ // ... std::cout << "RESULT: " << component->Operation(); // ... }
/** * Thanks to the fact that the child-management operations are declared in the * base Component class, the client code can work with any component, simple or * complex, without depending on their concrete classes. */ voidClientCode2(Component *component1, Component *component2){ // ... if (component1->IsComposite()) { component1->Add(component2); } std::cout << "RESULT: " << component1->Operation(); // ... }
/** * This way the client code can support the simple leaf components... */
intmain(){ Component *simple = new Leaf; std::cout << "Client: I've got a simple component:\n"; ClientCode(simple); std::cout << "\n\n"; /** * ...as well as the complex composites. */
Component *tree = new Composite; Component *branch1 = new Composite;
Component *leaf_1 = new Leaf; Component *leaf_2 = new Leaf; Component *leaf_3 = new Leaf; branch1->Add(leaf_1); branch1->Add(leaf_2); Component *branch2 = new Composite; branch2->Add(leaf_3); tree->Add(branch1); tree->Add(branch2); std::cout << "Client: Now I've got a composite tree:\n"; ClientCode(tree); std::cout << "\n\n";
std::cout << "Client: I don't need to check the components classes even when managing the tree:\n"; ClientCode2(tree, simple); std::cout << "\n";