组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使用的用户对单个对象和组合对象的使用具有一致性。
本文使用书中公司管理系统的事例,代码使用C++语言描述,代码存在的不足或问题有望各位指出。
(1)组合模式代码框架
//组合模式
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
class Component
{
public:
Component(){}
virtual ~Component(){}
Component(string name)
{
this->name =name;
}
virtual void Add(Component *c)=0;
virtual void Remove(Component *c)=0;
virtual void Display(int depth) =0;
protected:
string name;
};
class Leaf: public Component
{
public:
Leaf(){}
~Leaf(){}
Leaf(string name)
{
this->name =name;
}
void Add(Component *c) override
{
cout <<"Cannot add to a leaf!"<<endl;
}
void Remove(Component *c) override
{
cout << "Cannot remove from a leaf!" <<endl;
}
void Display(int depth) override
{
while(depth > 0)
{
cout << "_" ;
depth--;
}
cout << name<<endl;
}
};
class Composite: public Component
{
public:
Composite(){}
~Composite(){}
Composite(string name)
{
this->name =name;
}
void Add(Component *c) override
{
children.push_back(c);
}
void Remove(Component *c) override
{
auto it = children.begin();
for(;it !=children.end();it++)
{
if(*it == c)
break;
}
if(it!=children.end())
{
children.erase(it);
}
}
void Display(int depth) override
{
int depthOri = depth;
while(depth>0)
{
cout <<'_';
depth--;
}
cout <<name<<endl;
for(auto c:children)
c->Display(depthOri+2);
}
private:
vector<Component*> children;
};
int main()
{
Composite *root = new Composite("root");
root->Add(new Leaf("Leaf A"));
root->Add(new Leaf("Leaf B"));
Composite *comp = new Composite("Composite X");
comp->Add(new Leaf("Leaf XA"));
comp->Add(new Leaf ("Leaf XB"));
root->Add(comp);
Composite *comp2 =new Composite("Composite XY");
comp2->Add(new Leaf("Leaf XYA"));
comp2->Add(new Leaf("Leaf XYB"));
comp->Add(comp2);
root->Add(new Leaf("Leaf C"));
Leaf *leaf = new Leaf("leaf D");
root->Add(leaf);
root->Remove(leaf);
root->Display(1);
delete root;
delete comp;
delete comp2;
delete leaf;
return 0;
}
(2)公司管理系统使用组合模式
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Company
{
public:
Company(){}
virtual ~Company(){}
Company(string name)
{
this->name =name;
}
virtual void Add(Company *c) =0;
virtual void Remove(Company *c) =0;
virtual void Display(int depth) =0;
virtual void lineOfDuty() =0;
protected:
string name;
};
class ConcreteCompany :public Company
{
public:
ConcreteCompany(){}
~ConcreteCompany(){}
ConcreteCompany(string name)
{
this->name =name;
}
void Add(Company *c) override
{
children.push_back(c);
}
void Remove(Company *c) override
{
auto it = children.begin();
for(;it!=children.end();it++)
{
if(*it ==c)
break;
}
if(it!=children.end())
{
children.erase(it);
}
}
void Display( int depth) override
{
int depthOri = depth;
while(depth>0)
{
cout <<'_';
depth--;
}
cout <<name<<endl;
for(auto c:children)
c->Display(depthOri+2);
}
void lineOfDuty() override
{
for(auto c:children)
{
c->lineOfDuty();
}
}
private:
vector<Company*>children;
};
class HRDepartment : public Company
{
public:
HRDepartment(){}
~HRDepartment(){}
HRDepartment(string name)
{
this->name =name;
}
void Add(Company *c) override
{
}
void Remove(Company *c) override
{
}
void Display(int depth) override
{
while(depth>0)
{
cout <<'_';
depth--;
}
cout <<name<<endl;
}
void lineOfDuty() override
{
cout << name << "员工招聘培训管理" <<endl;
}
};
class FinanceDepartment : public Company
{
public:
FinanceDepartment(){}
~FinanceDepartment(){}
FinanceDepartment(string name)
{
this->name =name;
}
void Add(Company *c) override
{
}
void Remove(Company *c) override
{
}
void Display(int depth) override
{
while(depth>0)
{
cout <<"_";
depth--;
}
cout << name<<endl;
}
void lineOfDuty() override
{
cout << name <<"公司财务收支管理"<<endl;
}
private:
};
int main()
{
ConcreteCompany *root = new ConcreteCompany("北京总公司");
root->Add(new HRDepartment("总公司人力资源部"));
ConcreteCompany *comp = new ConcreteCompany("上海华东分公司");
comp->Add(new HRDepartment("华东分公司人力资源部"));
comp->Add(new FinanceDepartment("华东分公司财务部"));
root->Add(comp);
ConcreteCompany *comp1 = new ConcreteCompany("南京办事处");
comp1->Add(new HRDepartment("南京办事处人力资源部"));
comp1->Add(new FinanceDepartment("南京办事处财务部"));
root->Add(comp1);
ConcreteCompany *comp2 = new ConcreteCompany("杭州办事处");
comp2->Add(new HRDepartment("杭州办事处人力资源部"));
comp2->Add(new FinanceDepartment("杭州办事处财务部"));
root->Add(comp2);
root->Display(1);
root->lineOfDuty();
delete root;
delete comp;
delete comp1;
delete comp2;
return 0;
}
组合模式的好处
1、组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去,客户端代码,任何用到基本对象的地方都可以使用组合对象了。
2、用户是不用关心到底是处理一个叶结点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。
3、组合模式让客户可以一致地使用组合结构和单个对象。