【C++】Chapter15:组合模式

组合模式(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

【C++】Chapter15:组合模式_第1张图片

(1)Component : Company.h

#ifndef _COMPANY_H_ #define _COMPANY_H_ #include <string> #include <iostream> using namespace std; class Company { public: Company(const string& strName) : m_strName(strName) { } virtual void Add(Company* pCompany) = 0; virtual void Remove(Company* pCompany) = 0; virtual void Display(const int nDepth) = 0; virtual void Duty(void) = 0; private: string m_strName; }; #endif// _COMPANY_H_

 

(2)Leaf&Composite : LeafAndComposite.h

/************************************************************************ * description: 具体公司类 实现接口 树枝节点 * remark: ************************************************************************/ #ifndef _LEAF_COMPOSITE_H_ #define _LEAF_COMPOSITE_H_ #include <list> #include "Company.h" class ConcreteCompany : public Company { public: ConcreteCompany(const string& strName) : Company(strName) , m_strName(strName) { m_lstCompany.clear(); } void Add(Company* pCompany) { m_lstCompany.push_back(pCompany); } void Remove(Company* pCompany) { m_lstCompany.remove(pCompany); } void Display(const int nDepth) { string strDepth; for (int nCount = 0; nCount < nDepth; ++nCount) { strDepth.append("—"); } strDepth.append(m_strName); cout << strDepth << endl; list<Company*>::iterator Iter = m_lstCompany.begin(); for ( ; Iter != m_lstCompany.end(); Iter++) { (*Iter)->Display(nDepth + 2); } } // 履行职责 void Duty() { list<Company*>::iterator Iter = m_lstCompany.begin(); for ( ; Iter != m_lstCompany.end(); Iter++) { (*Iter)->Duty(); } } private: list<Company*> m_lstCompany; string m_strName; }; class HRDepartment : public Company { public: HRDepartment(const string& strName) : Company(strName) , m_strName(strName) { } void Add(Company* pCompany){} void Remove(Company* pCompany){} void Display(const int nDepth) { string strDepth; for (int nCount = 0; nCount < nDepth; ++nCount) { strDepth.append("—"); } strDepth.append(m_strName); cout << strDepth << endl; } void Duty() { cout << m_strName << "员工招聘培训管理" << endl; } private: string m_strName; }; class FinanceDepartment : public Company { public: FinanceDepartment(const string& strName) : Company(strName) , m_strName(strName) { } void Add(Company* pCompany){} void Remove(Company* pCompany){} void Display(const int nDepth) { string strDepth; for (int nCount = 0; nCount < nDepth; ++nCount) { strDepth.append("—"); } strDepth.append(m_strName); cout << strDepth << endl; } void Duty() { cout << m_strName << "公司财务收支管理" << endl; } private: string m_strName; }; #endif// _LEAF_COMPOSITE_H_

 

(3)客户端:CompositeApp.cpp

// CompositeApp.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "LeafAndComposite.h" void FreePtr(void* vPtr) { if (NULL != vPtr) { delete vPtr; vPtr = NULL; } } int _tmain(int argc, _TCHAR* argv[]) { ConcreteCompany* pRoot = NULL; pRoot = new ConcreteCompany("银河系总公司"); if (NULL != pRoot) { pRoot->Add(new HRDepartment("银河系总公司人力资源部")); pRoot->Add(new FinanceDepartment("银河系总公司财务部")); ConcreteCompany* pSubComp = NULL; pSubComp = new ConcreteCompany("太阳系分公司"); if (NULL != pSubComp) { pSubComp->Add(new HRDepartment("太阳系分公司人力资源部")); pSubComp->Add(new FinanceDepartment("太阳系分公司财务部")); } pRoot->Add(pSubComp); ConcreteCompany* pSubCompEarth = NULL; pSubCompEarth = new ConcreteCompany("地球分公司"); if (NULL != pSubCompEarth) { pSubCompEarth->Add(new HRDepartment("地球分公司人力资源部")); pSubCompEarth->Add(new FinanceDepartment("地球分公司财务部")); } pSubComp->Add(pSubCompEarth); ConcreteCompany* pSubCompAsia = NULL; pSubCompAsia = new ConcreteCompany("亚洲分公司"); if (NULL != pSubCompAsia) { pSubCompAsia->Add(new HRDepartment("亚洲分公司人力资源部")); pSubCompAsia->Add(new FinanceDepartment("亚洲分公司财务部")); } pSubCompEarth->Add(pSubCompAsia); ConcreteCompany* pSubCompAfrica = NULL; pSubCompAfrica = new ConcreteCompany("非洲分公司"); if (NULL != pSubCompAfrica) { pSubCompAfrica->Add(new HRDepartment("非洲分公司人力资源部")); pSubCompAfrica->Add(new FinanceDepartment("非洲分公司财务部")); } pSubCompEarth->Add(pSubCompAfrica); cout << "结构图" << endl; pRoot->Display(0); cout << "/n职责" << endl; pRoot->Duty(); system("pause"); FreePtr(pSubCompAfrica); FreePtr(pSubCompAsia); FreePtr(pSubCompEarth); FreePtr(pSubComp); FreePtr(pRoot); } return 0; }

 

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

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

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

你可能感兴趣的:(【C++】Chapter15:组合模式)