组合模式
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
(将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)
通用类图
抽象构件角色类
定义参加组合对象的公有方法和属性,可以定义一下默认的行为或属性
叶子构件类
叶子对象,其下再也没有其他的分支,遍历的最小单位,继承抽象构件角色类
树枝构件类
组合树枝节点和叶子节点形成一个树形结构,继承抽象构件角色类,并且与之是整体与部分关系
通用源码
//抽象构件类
class Component {
public:
virtual void doSomething() {
//业务逻辑
}
};
//树枝构件类,组合模式的重点
class Composite : public Component {
private:
//构件容器
vector<Component*> vc;
public:
//增加一个叶子构件或树枝构件
void add(Component *c) { vc.push_back(c);}
//删除一个叶子构件或树枝构件
void remove(Component *c) {
auto iter = vc.find(vc.begin(), vc.end(), c);
vc.erase(c);
}
//获得分支下的所有叶子构件和树枝构件
vector<Component*> getChildren() {
return vc;
}
};
//叶子构件类
class Leaf : public Component {
public:
void doSomething() {
}
};
优点
高层模块调用简单
节点自由增加,符合开闭原则
缺点
违背依赖倒置原则,没有面向接口编程
使用场景
维护和展示部分-整体的场景,如树性菜单、文件和文件夹管理
从一个整体中能够独立出部分模块或功能的场景
扩展
与关系数据库结合使用,能够轻松的实现树的组装
透明的组合模式,把树枝构件中的方法放到抽象类中实现,遵循依赖倒置原则
组合模式的遍历,增加设置父节点的方法,实现从底往上的遍历
示例代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Corp {
public:
Corp(const string& n, const string& p, int s): name(n), position(p), salary(s) { }
string getinfo() {
string info = name + ", "+ position + ", ";
info += to_string(salary);
return info;
}
private:
string name;
string position;
int salary;
};
class Leaf : public Corp {
public:
Leaf(const string& n, const string& p, int s): Corp(n, p, s) { }
};
class Branch : public Corp {
public:
Branch(const string& n, const string& p, int s): Corp(n, p, s){ }
void addSubordinate(Corp *ic) {
vIc.push_back(ic);
}
vector<Corp*> getSubordinate() {
return vIc;
}
private:
vector<Corp*> vIc;
};
int main() {
Branch ceo("zzzl", "ceo", 10000);
Branch dev("lzzl", "dev", 8000);
Branch sal("llzl", "sal", 8000);
Leaf a("zzl1", "dev1", 5000);
Leaf b("zzl2", "dev2", 5000);
Leaf c("lzl1", "sal1", 5000);
Leaf d("lzl2", "sal2", 5000);
Leaf e("lll", "ass", 5000);
ceo.addSubordinate(&dev);
ceo.addSubordinate(&sal);
ceo.addSubordinate(&e);
dev.addSubordinate(&a);
dev.addSubordinate(&b);
sal.addSubordinate(&c);
sal.addSubordinate(&d);
cout << ceo.getinfo() << endl;
vector<Branch> vb;
vb.push_back(ceo);
vb.push_back(dev);
vb.push_back(sal);
for(i : vb) {
vector<Corp*> v = i.getSubordinate();
for(j : v)
cout << j->getinfo() << endl;
}
return 0;
}