标签:
23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite
2016-07-22
(www.cnblogs.com/icmzn)
模式理解
1. Composite组合模式
又称为部分整体模式,主要用来描述部分与整体的关系。
将对象组合成树状结构以表示“部分-整体”的层次结构,是用户对“单个对象”和“组合对象”的使用具有一致性。
一般该模式具有三个角色:
(1)AbsComponent角色:一般为抽象父类,抽象“单个对象”“组合对象”公共的行为和方法,可以提供一些默认的方法或行为实现。
(2)Leaf角色:描述的是“单个对象”,具有不能再细分的对象,成为树叶。
(3)Composite:组合对象,可以成为“树枝”角色,同时完成对lefa,和composite角色的管理组织,一般用Vector类型实现,
从而形成一个完整的Tree结构,完成由上到下的遍历。
Leaf和Composite都要继承抽象AbsComponent类,
如果在Abscomponent类中添加一个指向自己类型的成员,则可以实现又下到上的遍历。
2. Composite优点
(1)高层调用很简单
因为一棵树的所有结构都是抽象的CAbsComposite的派生类,所以局部枝叶或者树枝没有区别,高层对枝叶或者树枝的处理都一样,简化了高层的代码
具体的处理交给底层细节。
(2)节点扩展自由
使用组合模式,对枝叶或者树枝的修改很容易。
3. Composite适用场景
(1)维护和展示具有整体部分的场景
(2)只要是树形结构,就一定考虑使用组合模式
4. Composite讨论
(1) 组合模式的实现方式有两种:安全模式,透明模式
安全模式:组合对象角色单独完成对Leaf 树叶 和Composite 树枝的管理,在高层的遍历访问时,不会出现通过Leaf的指针操作Composite的行为方法异常
透明模式:对结构的管理放在抽象AbsComponent角色中,则高层遍历的时候,因为Leaf树叶以及Composite树枝行为都一样,随意对高层来说是透明的,但是
会出现误调用的异常。
在C++中可以通过dynamic_cast<>来在运行时完成对实际指针所质量的派生类的转换,可以在此之前使用typeid(p) == typeid(ClassA) 来判定是否是需要的处理类型
(2)(1)vector中保留指针,删除的时候不delte管理的内容;(2)保留管理对象的副本,
从何效率,采取第一种
程序实现(C++)
Composite.h
1 #pragma once 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 //Composite模式 6 /* 7 组合模式用于管理一个树状结构的模型,故采用此模式管理学校的常用树状的解构层次,并且采用安全实现方式。 8 (1)校长 9 (2)老师 10 (3)学生 11 具有反向遍历功能, 12 */ 13 using namespace std; 14 class CAbsPersonComponent 15 { 16 public: 17 CAbsPersonComponent(const string& name, int age, const string& address) :m_strName(name), m_iAge(age), m_strAddress(address) 18 { 19 m_pParent = nullptr; 20 }; 21 ~CAbsPersonComponent() 22 { 23 //指向父类的指针,析构的时候不用收回空间 24 //m_pParent = nullptr; 25 }; 26 public: 27 bool operator== (const CAbsPersonComponent& person) 28 { 29 return (m_strName == person.m_strName) && (m_iAge == person.m_iAge) && (m_strAddress.compare(person.m_strAddress) == 0); 30 //if (m_strName != person.m_strName) 31 // return m_strName.compare(person.m_strName); 32 //else if (m_iAge != person.m_iAge) 33 // return m_iAge - person.m_iAge; 34 //else 35 // return m_strAddress.compare(person.m_strAddress); 36 } 37 protected: 38 // 39 virtual string getMyShenFen() = 0; 40 protected://需要派生类操作所以最好是protected 41 string m_strName; 42 int m_iAge; 43 string m_strAddress; 44 45 CAbsPersonComponent* m_pParent;//保留指向父类的指针,实现由下向上遍历 46 47 public: 48 //共有的行为属性 49 virtual void getInfo() 50 { 51 cout << "姓名:" << m_strName << "年龄:" << m_iAge << "地址:" << m_strAddress << "身份: " << getMyShenFen() << endl; 52 53 }; 54 virtual void setParent(CAbsPersonComponent* person) 55 { 56 this->m_pParent = person; 57 } 58 virtual CAbsPersonComponent* getParent() 59 { 60 return m_pParent; 61 } 62 }; 63 64 /* 65 Leaf结构定义,即学生身份的定义 66 */ 67 #define KEMU 3//定义三门成绩 68 class CStudentLeaf : public CAbsPersonComponent 69 { 70 public: 71 CStudentLeaf(const string& name, int age, const string& address, const double scores[]) : 72 CAbsPersonComponent(name, age, address) 73 { 74 for (int i = 0; i < KEMU; i++) 75 { 76 m_dScores[i] = scores[i]; 77 } 78 } 79 protected: 80 double m_dScores[KEMU]; 81 public: 82 //叶子结构特有的行为 83 void setScores(const double scores[]) 84 { 85 for (int i = 0; i < KEMU; i++) 86 { 87 m_dScores[i] = scores[i]; 88 } 89 } 90 void getScores() 91 { 92 cout << "学生分数: " << endl; 93 for (auto t : m_dScores) 94 { 95 cout << t << " "; 96 } 97 cout << endl; 98 } 99 string getMyShenFen() override 100 { 101 return "学生"; 102 } 103 }; 104 /* 105 树枝组合结构composite, 校长,老师都是管理者 106 因为管理者与被管理者只是在逻辑上存在,并不会应为一个管理者的删除,从而所有的Leaf对象都会删除。 107 所以(1)vector中保留指针,删除的时候不delte管理的内容;(2)保留管理对象的副本, 108 从何效率,采取第一种 109 */ 110 111 class CManagerComposite : public CAbsPersonComponent 112 { 113 public: 114 CManagerComposite(const string& name, int age, const string& address) : 115 CAbsPersonComponent(name, age, address) 116 { 117 } 118 119 public: 120 //树枝(树根)结构特有的行为 121 void addPersonComponent(CAbsPersonComponent* pPerson) 122 { 123 pPerson->setParent(this); 124 m_vecFellowers.push_back(pPerson); 125 } 126 /* 127 删除只删除管理的指针,不实际删除对象 128 */ 129 void removePersonComponent(CAbsPersonComponent* pPerson) 130 { 131 //m_vecFellowers.erase(&pPerson); 132 133 auto temp = m_vecFellowers.begin(); 134 for (; temp != m_vecFellowers.end(); temp++) 135 { 136 //比较对象比较,或者利用对象地址比较 137 if (*(*temp) == *pPerson) 138 break; 139 } 140 if (temp != m_vecFellowers.end()) 141 m_vecFellowers.erase(temp); 142 } 143 //返回vector对象的const 引用(提高效率) 144 const vector<CAbsPersonComponent*>& getFellows() 145 { 146 return m_vecFellowers; 147 } 148 string getMyShenFen() override 149 { 150 if (m_pParent) 151 return "老师"; 152 else 153 return "校长"; 154 } 155 private: 156 vector<CAbsPersonComponent*> m_vecFellowers;//管理者管理的人员 157 };
(1)模板应用
main.cpp
1 // Composite.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "CompositeDef.h" 6 7 static void getTreeMap(CAbsPersonComponent* p) 8 { 9 //cout << "当前类的名字: " << typeid(*p).name(); 10 p->getInfo(); 11 if (typeid(*p) == typeid(CManagerComposite)) 12 { 13 CManagerComposite* pTem = dynamic_cast<CManagerComposite*>(p); 14 vector<CAbsPersonComponent*> vector = pTem->getFellows();//引用 15 for (auto temp : vector) 16 { 17 getTreeMap(temp); 18 } 19 } 20 //其他情况s说明是叶子结构,不在处理 21 //else if (typeid(*p) == typeid(CStudentLeaf)) 22 //{ 23 24 //} 25 26 } 27 28 int _tmain(int argc, _TCHAR* argv[]) 29 { 30 //定义校长 31 CManagerComposite root("张百顺", 46, "A省B中全区"); 32 33 CManagerComposite a("博预期", 35, "A省B中全区"); 34 CManagerComposite b("张百顺", 46, "A省B中全区"); 35 CManagerComposite c("卢梦雅", 33, "A省B中全区"); 36 double scores1[] { 3.4, 33.3, 75.5 }; 37 double scores2[] { 4.4, 33.3, 75.5 }; 38 double scores3[] { 5.4, 37.3, 55.5 }; 39 double scores4[] { 6.4, 33.3, 75.5 }; 40 double scores5[] { 7.4, 33.3, 65.5 }; 41 double scores6[] { 9.4, 33.3, 55.5 }; 42 43 CStudentLeaf a1("a1", 16, "A省B中全区", scores1); 44 CStudentLeaf a2("a2", 16, "A省B中全区", scores1); 45 CStudentLeaf b1("b1", 16, "A省B中全区", scores1); 46 CStudentLeaf b2("b2", 16, "A省B中全区", scores1); 47 CStudentLeaf c1("c1", 16, "A省B中全区", scores1); 48 CStudentLeaf c2("c2", 16, "A省B中全区", scores1); 49 50 if (root == b) 51 cout << "root 与 b 相等" << endl; 52 53 root.addPersonComponent(&a); 54 root.addPersonComponent(&b); 55 root.addPersonComponent(&c); 56 57 a.addPersonComponent(&a1); 58 a.addPersonComponent(&a2); 59 b.addPersonComponent(&b1); 60 b.addPersonComponent(&b2); 61 c.addPersonComponent(&c1); 62 c.addPersonComponent(&c2); 63 64 65 getTreeMap(&root); 66 root.removePersonComponent(&a); 67 c.removePersonComponent(&c1); 68 69 cout << endl; 70 getTreeMap(&root); 71 72 cout << endl; 73 b1.getParent()->getInfo(); 74 75 system("pause"); 76 return 0; 77 }
(2)输出展示
23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite
标签:
原文地址:http://www.cnblogs.com/icmzn/p/5697258.html