将对象组合成树形结构以表示“部分 — 整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
a1 定义组件类Compoment,定义四个接口函数add()、remove()、findChild()、operation(); a2 定义一个叶节点类Leaf,定义重写操作函数operation(); a3 定义一个子节点枝类重写基类四个接口函数add()、remove()、findChild()、operation();
CompositePattern.cpp
#include <iostream> #include <string> #include <vector> using namespace std; #define DELETE(pointer) delete (pointer); (pointer)=nullptr class Compoment { public: virtual ~Compoment() { cout << "~Compoment()" << endl; } virtual void operation() = 0; virtual void add(Compoment *com){} virtual void remove(Compoment *com){} virtual Compoment* findChild(int index) { return nullptr; } }; class Leaf : public Compoment { int num; public: Leaf(int num) :num(num) {} ~Leaf(){ cout << "~Leaf()" << num << endl; } virtual void operation() override { cout << "Leaf::operation()" << num << endl; } }; class Composite : public Compoment { vector<Compoment*> coms; public: Composite() :coms(vector<Compoment*>()) {} ~Composite() { // 如果后面被继承,则需要声明为虚析构函数 cout << "~Composite()" << endl; for (auto it = coms.begin(); it != coms.end(); ++it) if ((*it) != nullptr) { DELETE((*it)); } } void operation() { cout << "Composite::operation()" << endl; for (auto it : coms) { it->operation(); } } void add(Compoment *com) { coms.push_back(com); } void remove(Compoment *com) { auto it = std::find(coms.begin(), coms.end(), com); if ((*it) != nullptr) coms.erase(it); } Compoment* findChild(int index) { if (index < 0 || index >= coms.size()) { return nullptr; } return coms[index]; } }; void doCompositePattern() { cout << " ------------- com1->operation() ------------- " << endl; Compoment *com1 = new Composite(); com1->add(new Leaf(1)); com1->add(new Leaf(2)); com1->add(new Leaf(3)); com1->operation(); cout << "\n ------------- com2->operation() ------------- " << endl; Compoment *com2 = new Composite(); com2->add(new Leaf(1)); com2->add(com1); // 注意:这里已经把指针*com1加入了com2的vector指针列表,所以不能在外部手动释放com1内存,此时com1所指向的内存有两个指针(外面的*com1和vector里面的*com1) com2->operation(); cout << "\n ------------- com2->findChild() ------------- " << endl; auto com3 = com2->findChild(0); if (com3 != nullptr) { cout << "\n ------------- com3->operation() ------------- " << endl; com3->operation(); } cout << "\n ------------- delete com2 ------------- " << endl; DELETE(com2); // 只需要释放指针*com2就行,里面数组vector维护了指针*com1地址,com2对象析构时会自动释放数组所有堆内存 }mian.cpp
#include <iostream> extern void doCompositePattern(); int main() { doCompositePattern(); system("pause"); return 1; }组合模式的核心在于对象组合的树形结构,即“整体—部分”的思想,跟装饰者模式结构类似,但是侧重点不同。装饰者模式主要在于不添加子类的前提下给对象增加职责,而组合模式在于给对象组合成一个“整体—部分”的树形结构来调用。 注意:在使用时,要特别注意内存的释放,本文没有使用智能指针主要是为了熟悉内存管理,在项目中可以考虑上智能指针防止出现野指针和内存非法访问!
C++设计模式-Composite组合模式 C++组合模式 陈建忠设计模式(参考:哔哩哔哩C++设计模式!!!) Erich Gamma,Richard Helm.《设计模式 可复用面向对象软件的基础》[M].机械工业出版社,2019: