组合模式,将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
透明方式和安全方式
透明方式,就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶结点和枝结点对于外界没有区别,它们具有完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add、Remove方法的功能,所以实现它是没有意义的。
安全模式,就是在Component接口中不去声明Add和Remove方法。那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法。不过由于不透明,所以树叶和树枝类将不具备相同的接口,客户端的调用需要做相应的判断,带来了不便。
何时使用组合模式
需求中是体现部分与整体层次的结构时,希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式。
#include <iostream>
#include <list>
using namespace std;
class Company //公司抽象类
{
string m_name; //公司名和部门名
public:
Company(string name):m_name(name){}; //构造函数传入公司名字
string getname(){return m_name;} //获取名字
virtual void Add(Company* c) = 0; //增加公司名字或者部门名字
virtual void Remove(Company* c) = 0; //删除公司名字或者部门名字
virtual void Display(int dapth) = 0; //打印公司名字或者部门名字
virtual void LineOfDuty() = 0; //打印部门职责
};
class RealCompany : public Company //具体公司类
{
list<Company*> link; //链表存放各个公司
list<Company*>::iterator it; //链表迭代器
public:
RealCompany(string name):Company(name){}; //构造函数传入公司名字
void Add(Company* c) //增加名字结点
{
link.push_back(c);
}
void Remove(Company* c) //删除名字结点
{
link.remove(c);
}
void Display(int dapth) //打印公司名字或者部门名字
{
cout<<"-"<<this->getname()<<endl;
for(it = link.begin(); it != link.end(); it++)
{
for(int i = 0; i < dapth; i++)
cout<<"-";
(*it)->Display(dapth);
}
}
void LineOfDuty() //打印部门职责
{
for(it = link.begin(); it != link.end(); it++)
{
(*it)->LineOfDuty();
}
}
};
class HRDepartmemt : public Company //人力资源部
{
public:
HRDepartmemt(string name):Company(name){}; //构造函数传入公司名字
void Add(Company* c) //没用到的方法
{
return;
}
void Remove(Company* c) //没用到的方法
{
return;
}
void Display(int dapth) //打印部门名字
{
cout<<this->getname()<<endl;
}
void LineOfDuty() //打印部门职责
{
cout<<this->getname()<<"员工招聘培训管理"<<endl;
}
};
class FinDepartmemt : public Company //财务部
{
public:
FinDepartmemt(string name):Company(name){}; //构造函数传入公司名字
void Add(Company* c) //没用到的方法
{
return;
}
void Remove(Company* c) //没用到的方法
{
return;
}
void Display(int dapth) //打印部门名字
{
cout<<this->getname()<<endl;
}
void LineOfDuty() //打印部门职责
{
cout<<this->getname()<<"公司财务收支管理"<<endl;
}
};
int main()
{
RealCompany* root = new RealCompany("北京总公司");
root->Add((new HRDepartmemt("总公司人力资源部")));
root->Add((new FinDepartmemt("总公司财务部")));
RealCompany* shanghai = new RealCompany("上海分公司");
shanghai->Add((new HRDepartmemt("华东分公司人力资源部")));
shanghai->Add((new FinDepartmemt("华东分公司财务部")));
root->Add(shanghai);
RealCompany* nanjing = new RealCompany("南京办事处");
nanjing->Add((new HRDepartmemt("南京办事处人力资源部")));
nanjing->Add((new FinDepartmemt("南京办事处财务部")));
root->Add(nanjing);
cout<<"\n结构图:"<<endl;
root->Display(1);
cout<<"\n职责:"<<endl;
root->LineOfDuty();
root->Remove(nanjing);
cout<<"\n结构图:"<<endl;
root->Display(1);
cout<<"\n职责:"<<endl;
root->LineOfDuty();
return 0;
}
显示结果:
[hjf@hjf 设计模式]$ ./a.out
结构图:
-北京总公司
-总公司人力资源部
-总公司财务部
--上海分公司
-华东分公司人力资源部
-华东分公司财务部
--南京办事处
-南京办事处人力资源部
-南京办事处财务部
职责:
总公司人力资源部员工招聘培训管理
总公司财务部公司财务收支管理
华东分公司人力资源部员工招聘培训管理
华东分公司财务部公司财务收支管理
南京办事处人力资源部员工招聘培训管理
南京办事处财务部公司财务收支管理
结构图:
-北京总公司
-总公司人力资源部
-总公司财务部
--上海分公司
-华东分公司人力资源部
-华东分公司财务部
职责:
总公司人力资源部员工招聘培训管理
总公司财务部公司财务收支管理
华东分公司人力资源部员工招聘培训管理
华东分公司财务部公司财务收支管理