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

(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;
}

 

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

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

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

 

 

posted @ 2010-10-12 20:30  奋斗の机器  阅读(270)  评论(0编辑  收藏  举报