将对象组合成树形结构以表示“部分-整体”的层次结构。组合使得用户对单个对象和组合对象的使用具有一致性。注意两个字“树形”。这种树形结构在现实生活中随处可见,比如一个集团公司,它有一个母公司,下设很多家子公司。不管是母公司还是子公司,都有各自直属的财务部、人力资源部、销售部等。对于母公司来说,不论是子公司,还是直属的财务部、人力资源部,都是它的部门。整个公司的部门拓扑图就是一个树形结构。
优点
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
使用场景
你想表示对象的部分-整体层次结构;
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
引用大话设计模式的片段:“当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。”
#include<iostream>
#include<cstring>
#include<list>
using namespace std;
class Company
{
public:
virtual void add(Company * company){}
virtual void show(int depth){}
protected:
string m_name;
};
//具体公司
class ConcreteCompany : public Company
{
public:
ConcreteCompany(string name)
{
m_name = name;
}
void add(Company * company)
{
m_listCompany.push_back(company);
}
void show(int depth)
{
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name << endl;
list<Company *>::iterator iter=m_listCompany.begin();
for(; iter != m_listCompany.end(); iter++) //显示下层结点
(*iter)->show(depth + 2);
}
private:
list<Company *> m_listCompany;
};
//具体的部门,财务部
class FinanceDepartment : public Company
{
public:
FinanceDepartment(string name)
{
m_name = name;
}
void show(int depth)
{
for(int i=0; i<depth; i++)
{
cout << "-";
}
cout << m_name << endl;
}
};
//具体的部门,人力资源部
class HRDepartment : public Company
{
public:
HRDepartment(string name)
{
m_name = name;
}
void show(int depth)
{
for(int i=0; i<depth; i++)
{
cout << "-";
}
cout << m_name << endl;
}
};
int main()
{
Company * root = new ConcreteCompany("总公司");
Company * leaf1 = new FinanceDepartment("财务");
Company * leaf2 = new HRDepartment("人事");
root->add(leaf1);
root->add(leaf2);
Company * mid1 = new ConcreteCompany("分公司A");
Company * leaf3 = new FinanceDepartment("财务");
Company * leaf4 = new HRDepartment("人事");
mid1->add(leaf3);
mid1->add(leaf4);
root->add(mid1);
Company * mid2 = new ConcreteCompany("分公司B");
Company * leaf5 = new FinanceDepartment("财务");
Company * leaf6 = new HRDepartment("人事");
mid2->add(leaf5);
mid2->add(leaf6);
root->add(mid2);
root->show(0);
delete leaf1; delete leaf2;
delete leaf3; delete leaf4;
delete leaf5; delete leaf6;
delete mid1; delete mid2;
delete root;
return 0;
}