组合模式:用来描述部分与整体的关系,定义为:将对象组合成树形结构来表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
类图摘自设计模式之禅:
抽象角色:组合对象的共有方法和属性。
叶子:最小单位,无分支
树枝:组合树枝和叶子形成树结构,常有容器和增删查函数。
优点:
高层模块调用简单(垂直管理),所有节点均是抽象角色,局部和整体对调用者来说没有区别,
高层不用管自己处理的是单个还是整体,简化了高层模块的代码。
节点水平自由增加,只要找到它的父节点就可,但不好垂直增加。
缺点:
有一个显而易见的缺陷就是抽象对象无法被定义,直接使用树形结构需要定义叶子对象和树枝对象,这不符合依赖倒转原则(用抽象代替细节,用基类指针指向子类对象),直接使用了实现类,使用时需有所注意。
在下面的代码示例中,管理者类Composite如果用其基类Component指针所指,就没有办法使用Add Component()或其他基类没有的函数。
使用场景:
维护和展示部分-整体关系的场景,如树形菜单、文件、文件夹管理。
从一个整体中能够独立出部分模块或功能的场景,例如复制文件夹,公司部门合并等。
实际中组装树的方法:
用数据库提供的数据表来存储一个树形结构,用for循环加上递归完成读取,这样的数据库叫关系型数据库,所以做项目肯定离不开数据库的。
组合模式的透明模式与安全模式:
安全模式:
将叶子和树枝功能分离,使其拥有不同的函数,树枝多出容器和增删查函数。
好处是安全稳定,缺点是不易扩展,违背依赖倒转原则。
透明模式:
将所有功能和数据封装在抽象类中,叶子和树枝共有,
好处是基本遵循了依赖倒转原则,提升了扩展性,
缺点是叶子可能调用其不支持的函数而导致意外报错或崩溃。
通过组合模式有了树形结构以后还有遍历的工作要做,很明显只需要在抽象对象中加入setParent()、getParent()、find()就可以了,而树枝需要给自己下一级的抽象对象排顺序,只需要在树枝节点中增加排序算法就可以了。
身边的组合模式:
省市县,族谱,xml,文件夹,到处都是。
代码示例:此为组合模式的安全模式代码,内容模拟管理层(Leader)与叶子(Worker)
class Component
{
public:
virtual void Operation() = 0;
protected:
int mNum;
};
class Leaf :public Component