组合模式
组合模式(Composite),将对象组合成树形结构以表示部分整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
使用场景
需求中是体现部分与整体层次的结构,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象。
优点:
- 组合模式定义了基本对象和组合对像的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
- 用户不用关心到底是处理一个叶节点还是处理一个组合组件,也用不着为定义组合而写一些选择判断语句了。简单点说,就是组合模式让客户可以一致地使用组合结构和单个对象。
结构图
example
实现总公司分公司,总分公司都有自己的人力资源部、财务部等。
// 抽象类 定义所有组件统一都要实现的接口
class component
{
protected:
string name;
public:
component(string s):name(s){};
string getName(){return name;}
virtual void add(component* c) = 0; // 增加下属组件
virtual void del(component* c) = 0; // 删除下属组件
virtual void duty() = 0; // 职责
virtual void display(int depth) = 0;
};
// 人事部
class Hr : public component {
public:
Hr(string s) : component(s){};
virtual void add(component* c){
cout << "人力资源部 不可继续添加节点" << endl;
}
virtual void del(component* c){
cout << "人力资源部 没有节点可以删除" << endl;
}
virtual void duty() {
cout << name << " 负责人事调整" << endl;
}
virtual void display(int depth) {
string sign(depth,'-');
cout << sign << name << endl;
}
};
// 财务部
class Finance : public component {
public:
Finance(string s) : component(s){};
virtual void add(component* c){
cout << "财务部 不可继续添加节点" << endl;
}
virtual void del(component* c){
cout << "财务部 没有节点可以删除" << endl;
}
virtual void duty() {
cout << name << " 负责财务清算" << endl;
}
virtual void display(int depth) {
string sign(depth,'-');
cout << sign << name << endl;
}
};
// 组合类 可以随意组合各级对象成为一个新的对象
class Composite : public component {
list<component*> comps;
public:
Composite(string s) : component(s){};
virtual void add(component* c){
comps.push_back(c);
}
virtual void del(component* c){
comps.remove(c);
}
virtual void duty() {
for (auto c : comps) {
// cout << c->getName() << " ";
c->duty();
}
}
virtual void display(int depth) {
string sign(depth,'-');
cout << sign << name << endl;
for (component* c : comps) {
c->display(depth+1);
}
}
};
int main()
{
component *x1 = new Hr("子公司X人事部");
component *x2 = new Finance("子公司X财务部");
component *x = new Composite("子公司X");
x->add(x1);
x->add(x2);
component *a = new Composite("总公司");
component *a1 = new Hr("人事部");
component *a2 = new Finance("财务部");
a->add(a1);
a->add(a2);
a->add(x);
a->display(1);
cout << "-----职责----" << endl;
a->duty();
return 0;
}
组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对家的类层次结构。这家公司开多少个以及多少级办事处都可以实现。