组合模式
将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
何时使用组合模式
需求中是体现部分与整体层次的结构时,希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑使用组合模式了。
组合模式的优点
基本对象可以被组合更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
用户不需要关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。
组合模式让客户可以一致地使用组合结构和单个对象
组合模式 – 公司管理系统
//组合模式 -- 公司管理系统
//公司类 抽象类
class Company
{
public:
Company() = default;
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 depth) = 0;
virtual void LineOfDuty() = 0; //履行职责
private:
string m_name;
};
//具体公司类 实现接口 树枝节点
class ConcreteCompany :public Company
{
public:
ConcreteCompany(string name) : Company(name){}
void Add(Company *c){ m_children.push_back(c); }
void Remove(Company *c){ m_children.remove(c); }
void Display(int depth)
{
cout << string(depth, '-') << GetName() << endl;
for (auto it = m_children.begin(); it != m_children.end(); ++it)
{
(*it)->Display(depth + 2);
}
}
void LineOfDuty()
{
for (auto it = m_children.begin(); it != m_children.end(); ++it)
{
(*it)->LineOfDuty();
}
}
private:
list<Company*> m_children;
};
//人力资源部 树叶节点
class HRDepartment :public Company
{
public:
HRDepartment(string name):Company(name){}
void Add(Company *c){}
void Remove(Company *c){}
void Display(int depth){ cout << string(depth, '-') << GetName() << endl; }
void LineOfDuty(){ cout << "1. 员工招聘" << GetName() << endl; }
};
//财务部 树叶节点
class Financeepartment :public Company
{
public:
Financeepartment(string name) :Company(name){}
void Add(Company *c){}
void Remove(Company *c){}
void Display(int depth){ cout << string(depth, '-') << GetName() << endl; }
void LineOfDuty(){ cout << "1. 财务支出" << GetName() << endl;}
};
测试程序:
int main()
{
ConcreteCompany *root = new ConcreteCompany("北京总公司");
root->Add(new HRDepartment("总公司人力资源部"));
root->Add(new Financeepartment("总公司财务部"));
ConcreteCompany *comp = new ConcreteCompany("南京办事处");
comp->Add(new HRDepartment("南京人力资源部"));
comp->Add(new Financeepartment("南京财务部"));
root->Add(comp);
ConcreteCompany *comp1 = new ConcreteCompany("江宁办事处");
comp1->Add(new HRDepartment("江宁人力资源部"));
comp1->Add(new Financeepartment("江宁财务部"));
comp->Add(comp1);
ConcreteCompany *comp2 = new ConcreteCompany("仙林办事处");
comp2->Add(new HRDepartment("仙林人力资源部"));
comp2->Add(new Financeepartment("仙林财务部"));
comp->Add(comp2);
//结构图
root->Display(1);
//职责
root->LineOfDuty();
system("pause");
return 0;
}