C++组合模式(Composite)

    xiaoxiao2022-07-14  161

    UML类图(仅供参考)如下:

    组合模式解决的问题:

    将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性,比如QT桌面应用开发框架中的控件

    源码

    #include <iostream> #include <vector> // Component抽象基类,相当于所有图形界面控件的公共父类一样 class CComponent { public: virtual ~CComponent() {} // 纯虚函数,只提供接口,没有默认的实现 virtual void Operation() = 0; // 虚函数,提供接口,有默认的实现就是什么都不做 virtual void Add(CComponent*) {} virtual void Remove(CComponent*) {} virtual CComponent* GetChild(int index) { return nullptr; } protected: CComponent() {} }; // 相当于最基本的控件,比如Button、Edit这样的 class CLeaf :public CComponent { public: // 每个控件都有自己的特殊功能 virtual void Operation() { std::cout << "CLeaf::Operation" << std::endl; } }; // 相当于一个对话框,上面还可以有很多控件在上面 class CComposite :public CComponent { public: CComposite() { pChildren = new std::vector<CComponent *>(); } ~CComposite() { for (auto &var : *pChildren) { if (nullptr != var) { // 注意,这里的控件有可能被添加到多个父控件里 // 但是只能释放一遍(这里有可能释放了很多遍,所以一个控件只能有一个父控件) // 建议这里的Add、Remove、GetChild方法都用类引用作为参数,这样就避免了上面的问题 // 而且也不用释放内存 delete var; var = nullptr; } } delete pChildren; } virtual void Operation() { std::cout << "CComposite::Operation" << std::endl; } // 添加一个子控件 virtual void Add(CComponent* com) { std::cout << "CComposite::Add" << std::endl; pChildren->push_back(com); } // 移除一个子控件 virtual void Remove(CComponent* com) { std::cout << "CComposite::Remove" << std::endl; auto var = std::find(pChildren->begin(), pChildren->end(), com); if (pChildren->end() != var) { pChildren->erase(var); } } // 获取一个子控件 virtual CComponent* GetChild(int index) { std::cout << "CComposite::GetChild" << std::endl; return nullptr; } protected: // 相当于所有子控件 std::vector<CComponent *> *pChildren; }; // 测试 int main() { // 不管是叶子Leaf还是Composite对象pRoot、pCom都实现了Operation接口,所以可以一致对待,直接调用Operation() // 体现了“使得用户对单个对象和组合对象的使用具有一致性” CComposite* pRoot = new CComposite(); // 组合对象添加叶子节点 pRoot->Add(new CLeaf()); // 这里的叶子再添加叶子是没有意义的。 // 由于叶子与组合对象继承了相同的接口,所以语法上是对的,实际上什么也没做(继承自基类Component的Add方法)。 // 叶子节点只实现了Operation方法,其他Add、Remove、GetChild都继承自基类,没有实际意义。 CLeaf* pLeaf1 = new CLeaf(); CLeaf* pLeaf2 = new CLeaf(); pLeaf1->Add(pLeaf2); pLeaf1->Remove(pLeaf2); // 执行叶子Operation操作 pLeaf1->Operation(); // 组合对象实现了基类Component的所有接口,所以可以做各种操作(Add、Remove、GetChild、Operation)。 CComposite* pCom = new CComposite(); // 组合对象添加叶子节点 pCom->Add(pLeaf1); // 组合对象添加叶子节点 pCom->Add(pLeaf2); // 执行组合对象Operation操作 pCom->Operation(); // 组合对象添加组合对象 pRoot->Add(pCom); // 执行组合对象Operation操作 pRoot->Operation(); pCom->Remove(pLeaf1); return 0; }

    好处

    1、高层模块调用简单。

    2、节点自由增加。

    最新回复(0)