• 设计模式9、组合模式 Composite


    解释说明:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。
    抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性
    树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点行程一个树形结构
    叶子节点(Left):叶子节点对象,其下再无分支,是系统层次遍历的最小单位
    优点:
        可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让 Client 忽略了层次的差异,方便对整个层次结构进行控制。
        Client 可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了 Client 的代码。
        在组合模式中,增加新的叶子构件和容器构件很方便,无须对现有类进行任何修改,符合“开闭原则”。
        为树形结构提供了一种灵活的解决方案,通过递归组合容器对象和叶子对象,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
    缺点:
        使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联。
    适用场景
        表示对象的“整体-部分”层次结构(树形结构)
        希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象
    1. #pragma once
    2. #include
    3. #include
    4. /****组合模式 Composite******/
    5. using namespace std;
    6. class Component
    7. {
    8. public:
    9. Component(string name) : m_strName(name) {}
    10. virtual ~Component() {}
    11. virtual void Add(Component* cmpt) = 0; // 添加构件
    12. virtual void Remove(Component* cmpt) = 0; // 删除构件
    13. virtual Component* GetChild(int index) = 0; // 获取构件
    14. virtual void Operation(int indent) = 0; // 显示构件(以缩进的方式)
    15. private:
    16. Component(); // 不允许
    17. protected:
    18. string m_strName;
    19. };
    20. #pragma once
    21. #include
    22. #include "component.h"
    23. #ifndef SAFE_DELETE
    24. #define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
    25. #endif
    26. class Composite : public Component
    27. {
    28. public:
    29. Composite(string name) : Component(name) {}
    30. virtual ~Composite() {
    31. while (!m_elements.empty()) {
    32. vector::iterator it = m_elements.begin();
    33. SAFE_DELETE(*it);
    34. m_elements.erase(it);
    35. }
    36. }
    37. void Add(Component* cmpt) {
    38. m_elements.push_back(cmpt);
    39. }
    40. void Remove(Component* cmpt) {
    41. vector::iterator it = m_elements.begin();
    42. while (it != m_elements.end()) {
    43. if (*it == cmpt) {
    44. SAFE_DELETE(cmpt);
    45. m_elements.erase(it);
    46. break;
    47. }
    48. ++it;
    49. }
    50. }
    51. Component* GetChild(int index) {
    52. if (index >= m_elements.size())
    53. return NULL;
    54. return m_elements[index];
    55. }
    56. // 递归显示
    57. void Operation(int indent) {
    58. string newStr(indent, '-');
    59. cout << newStr << "+ " << m_strName << endl;
    60. // 显示每个节点的孩子
    61. vector::iterator it = m_elements.begin();
    62. while (it != m_elements.end()) {
    63. (*it)->Operation(indent + 2);
    64. ++it;
    65. }
    66. }
    67. private:
    68. Composite(); // 不允许
    69. private:
    70. vector m_elements;
    71. };
    72. #pragma once
    73. #include "component.h"
    74. class Leaf : public Component
    75. {
    76. public:
    77. Leaf(string name) : Component(name) {}
    78. virtual ~Leaf() {}
    79. void Add(Component* cmpt) {
    80. cout << "Can't add to a Leaf" << endl;
    81. }
    82. void Remove(Component* cmpt) {
    83. cout << "Can't remove from a Leaf" << endl;
    84. }
    85. Component* GetChild(int index) {
    86. cout << "Can't get child from a Leaf" << endl;
    87. return NULL;
    88. }
    89. void Operation(int indent) {
    90. string newStr(indent, '-');
    91. cout << newStr << " " << m_strName << endl;
    92. }
    93. private:
    94. Leaf(); // 不允许
    95. };
    96. #include "composite.h"
    97. #include "leaf.h"
    98. int main()
    99. {
    100. // 创建一个树形结构
    101. // 创建根节点
    102. Component* pRoot = new Composite("江湖公司(任我行)");
    103. // 创建分支
    104. Component* pDepart1 = new Composite("日月神教(东方不败)");
    105. pDepart1->Add(new Leaf("光明左使(向问天)"));
    106. pDepart1->Add(new Leaf("光明右使(曲洋)"));
    107. pRoot->Add(pDepart1);
    108. Component* pDepart2 = new Composite("五岳剑派(左冷蝉)");
    109. pDepart2->Add(new Leaf("嵩山(左冷蝉)"));
    110. pDepart2->Add(new Leaf("衡山(莫大)"));
    111. pDepart2->Add(new Leaf("华山(岳不群)"));
    112. pDepart2->Add(new Leaf("泰山(天门道长)"));
    113. pDepart2->Add(new Leaf("恒山(定闲师太)"));
    114. pRoot->Add(pDepart2);
    115. // 添加和删除叶子
    116. pRoot->Add(new Leaf("少林(方证大师)"));
    117. pRoot->Add(new Leaf("武当(冲虚道长)"));
    118. Component* pLeaf = new Leaf("青城(余沧海)");
    119. pRoot->Add(pLeaf);
    120. // 小丑,直接裁掉
    121. pRoot->Remove(pLeaf);
    122. // 递归地显示组织架构
    123. pRoot->Operation(1);
    124. // 删除分配的内存
    125. SAFE_DELETE(pRoot);
    126. getchar();
    127. return 0;
    128. }

     

  • 相关阅读:
    矩池云如何自定义端口,访问自己的web项目
    数据库的建立、增、删、改、查
    C++数据结构类的自实现,封装栈,循环队列
    LeetCode刷题---142. 环形链表 II(双指针-快慢指针)
    创建一个双模式跨运行时的 JavaScript 包
    java计算机毕业设计校园临时用工网站MyBatis+系统+LW文档+源码+调试部署
    SpringCloud -Ribbon
    从Unix看文言文为什么短
    LinuxC/C++ 实现简单的TCP服务端
    从简单到复杂,MVI 架构定义与封装使用总结
  • 原文地址:https://blog.csdn.net/u013480226/article/details/133500040