Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1146702
  • 博文数量: 177
  • 博客积分: 761
  • 博客等级: 上士
  • 技术积分: 1518
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-04 22:37
文章分类

全部博文(177)

文章存档

2017年(1)

2016年(3)

2015年(33)

2014年(48)

2013年(60)

2012年(32)

分类: C/C++

2013-08-12 10:20:30

原文地址:组合模式 作者:xutianxi

组合模式(Composite)

将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

根据上图可以看出Component中纯虚函数Add、Remove。也就是说在Leaf类当中也有Add、Remove,树叶不是不可以再长分枝吗?呵呵~教材上把这种方式叫做透明方式

透明方式:也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。这 样实现Component接口的所有子类都具备了Add、Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,他们具备完全一致的行为接口。 但问题也很明显,因为leaf类本身不具备Add、Remov方法的功能,所以实现它是没有意义的。

如果不希望做这样的无用功?也就是leaf类当中不用Add和Remove方法。这样就需要安全方式

安全方式:子类的leaf不需要去实现Add、Remov等方法,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所有树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。

何时使用组合模式

当需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

 

 

实际应用

工程结构:

(1)Component : Company.h

(2)Leaf&Composite : LeafAndComposite.h

(3)客户端:CompositeApp.cpp

(1)Component : Company.h

  1. #ifndef _COMPANY_H_  
  2. #define _COMPANY_H_  
  3.   
  4. #include   
  5. #include   
  6. using namespace std;  
  7.   
  8. class Company  
  9. {  
  10. public:  
  11.     Company(const string& strName)   
  12.         : m_strName(strName)  
  13.     {  
  14.     }  
  15.   
  16.     virtual void Add(Company* pCompany) = 0;  
  17.     virtual void Remove(Company* pCompany) = 0;  
  18.     virtual void Display(const int nDepth) = 0;  
  19.     virtual void Duty(void) = 0;  
  20. private:  
  21.     string m_strName;  
  22. };  
  23.   
  24. #endif// _COMPANY_H_  

(2)Leaf&Composite : LeafAndComposite.h

  1. /************************************************************************ 
  2.  * description: 具体公司类 实现接口 树枝节点 
  3.  * remark:       
  4. ************************************************************************/  
  5. #ifndef _LEAF_COMPOSITE_H_  
  6. #define _LEAF_COMPOSITE_H_  
  7.   
  8. #include   
  9. #include "Company.h"  
  10.   
  11. class ConcreteCompany : public Company  
  12. {  
  13. public:  
  14.     ConcreteCompany(const string& strName)  
  15.         : Company(strName)  
  16.         , m_strName(strName)  
  17.     {  
  18.         m_lstCompany.clear();  
  19.     }  
  20.   
  21.     void Add(Company* pCompany)  
  22.     {  
  23.         m_lstCompany.push_back(pCompany);  
  24.     }  
  25.   
  26.     void Remove(Company* pCompany)  
  27.     {  
  28.         m_lstCompany.remove(pCompany);  
  29.     }  
  30.   
  31.     void Display(const int nDepth)  
  32.     {  
  33.         string strDepth;  
  34.         for (int nCount = 0; nCount < nDepth; ++nCount)  
  35.         {  
  36.             strDepth.append("—");  
  37.         }  
  38.         strDepth.append(m_strName);  
  39.         cout << strDepth << endl;  
  40.   
  41.         list::iterator Iter = m_lstCompany.begin();  
  42.         for ( ; Iter != m_lstCompany.end(); Iter++)  
  43.         {  
  44.             (*Iter)->Display(nDepth + 2);  
  45.         }  
  46.     }  
  47.   
  48.     // 履行职责  
  49.     void Duty()  
  50.     {  
  51.         list::iterator Iter = m_lstCompany.begin();  
  52.         for ( ; Iter != m_lstCompany.end(); Iter++)  
  53.         {  
  54.             (*Iter)->Duty();  
  55.         }  
  56.     }  
  57.   
  58. private:  
  59.     list  m_lstCompany;  
  60.     string          m_strName;  
  61. };  
  62.   
  63.   
  64. class HRDepartment : public Company  
  65. {  
  66. public:  
  67.     HRDepartment(const string& strName)  
  68.         : Company(strName)  
  69.         , m_strName(strName)  
  70.     {  
  71.     }  
  72.   
  73.     void Add(Company* pCompany){}  
  74.     void Remove(Company* pCompany){}  
  75.   
  76.     void Display(const int nDepth)  
  77.     {  
  78.         string strDepth;  
  79.         for (int nCount = 0; nCount < nDepth; ++nCount)  
  80.         {  
  81.             strDepth.append("—");  
  82.         }  
  83.         strDepth.append(m_strName);  
  84.         cout << strDepth << endl;  
  85.     }  
  86.   
  87.     void Duty()  
  88.     {  
  89.         cout << m_strName << "员工招聘培训管理" << endl;  
  90.     }  
  91.   
  92. private:  
  93.     string  m_strName;  
  94. };  
  95.   
  96. class FinanceDepartment : public Company  
  97. {  
  98. public:  
  99.     FinanceDepartment(const string& strName)  
  100.         : Company(strName)  
  101.         , m_strName(strName)  
  102.     {  
  103.     }  
  104.   
  105.     void Add(Company* pCompany){}  
  106.     void Remove(Company* pCompany){}  
  107.   
  108.     void Display(const int nDepth)  
  109.     {  
  110.         string strDepth;  
  111.         for (int nCount = 0; nCount < nDepth; ++nCount)  
  112.         {  
  113.             strDepth.append("—");  
  114.         }  
  115.         strDepth.append(m_strName);  
  116.         cout << strDepth << endl;  
  117.     }  
  118.   
  119.     void Duty()  
  120.     {  
  121.         cout << m_strName << "公司财务收支管理" << endl;  
  122.     }  
  123.   
  124. private:  
  125.     string  m_strName;  
  126. };  
  127.   
  128. #endif// _LEAF_COMPOSITE_H_  

(3)客户端:CompositeApp.cpp

  1. // CompositeApp.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "LeafAndComposite.h"  
  6.   
  7. void FreePtr(void* vPtr)     
  8. {     
  9.     if (NULL != vPtr)     
  10.     {     
  11.         delete vPtr;     
  12.         vPtr = NULL;     
  13.     }     
  14. }  
  15.   
  16. int _tmain(int argc, _TCHAR* argv[])  
  17. {  
  18.     ConcreteCompany* pRoot = NULL;  
  19.     pRoot = new ConcreteCompany("银河系总公司");  
  20.     if (NULL != pRoot)  
  21.     {  
  22.         pRoot->Add(new HRDepartment("银河系总公司人力资源部"));  
  23.         pRoot->Add(new FinanceDepartment("银河系总公司财务部"));  
  24.   
  25.         ConcreteCompany* pSubComp = NULL;  
  26.         pSubComp = new ConcreteCompany("太阳系分公司");  
  27.         if (NULL != pSubComp)  
  28.         {  
  29.             pSubComp->Add(new HRDepartment("太阳系分公司人力资源部"));  
  30.             pSubComp->Add(new FinanceDepartment("太阳系分公司财务部"));  
  31.         }  
  32.         pRoot->Add(pSubComp);  
  33.   
  34.         ConcreteCompany* pSubCompEarth = NULL;  
  35.         pSubCompEarth = new ConcreteCompany("地球分公司");  
  36.         if (NULL != pSubCompEarth)  
  37.         {  
  38.             pSubCompEarth->Add(new HRDepartment("地球分公司人力资源部"));  
  39.             pSubCompEarth->Add(new FinanceDepartment("地球分公司财务部"));  
  40.         }  
  41.         pSubComp->Add(pSubCompEarth);  
  42.   
  43.         ConcreteCompany* pSubCompAsia = NULL;  
  44.         pSubCompAsia = new ConcreteCompany("亚洲分公司");  
  45.         if (NULL != pSubCompAsia)  
  46.         {  
  47.             pSubCompAsia->Add(new HRDepartment("亚洲分公司人力资源部"));  
  48.             pSubCompAsia->Add(new FinanceDepartment("亚洲分公司财务部"));  
  49.         }  
  50.         pSubCompEarth->Add(pSubCompAsia);  
  51.   
  52.         ConcreteCompany* pSubCompAfrica = NULL;  
  53.         pSubCompAfrica = new ConcreteCompany("非洲分公司");  
  54.         if (NULL != pSubCompAfrica)  
  55.         {  
  56.             pSubCompAfrica->Add(new HRDepartment("非洲分公司人力资源部"));  
  57.             pSubCompAfrica->Add(new FinanceDepartment("非洲分公司财务部"));  
  58.         }  
  59.         pSubCompEarth->Add(pSubCompAfrica);  
  60.   
  61.         cout << "结构图" << endl;  
  62.         pRoot->Display(0);  
  63.   
  64.         cout << "\n职责" << endl;  
  65.         pRoot->Duty();  
  66.   
  67.         system("pause");  
  68.   
  69.         FreePtr(pSubCompAfrica);  
  70.         FreePtr(pSubCompAsia);  
  71.         FreePtr(pSubCompEarth);  
  72.         FreePtr(pSubComp);  
  73.         FreePtr(pRoot);          
  74.     }      
  75.       
  76.     return 0;  
  77. }  

组合模式定义了包含“人力资源部”和“财务部”这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象。

用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。

组合模式让客户可以一致地使用组合结构和单个对象。

阅读(814) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~