码迷,mamicode.com
首页 > 编程语言 > 详细

23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite

时间:2016-07-22 23:10:25      阅读:324      评论:0      收藏:0      [点我收藏+]

标签:

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!