组合模式 - Composite Pattern,也叫合成模式,又叫做部分-整体模式(Part-Whole)

WHAT

主要用来描述部分与整体的关系

定义

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

类图

Component抽象构建角色

定义参加组合对象的公有方法和属性

可以定义一些默认的行为和属性

public abstract class Component {
  // 个体和整体都具有的公有方法
  public void doSimething(){
    // 业务逻辑
  }
}

Leaf叶子构件

叶子对象,其下再也没有其他的分支,也就是遍历的最小单位

public class Leaf extends Component {
  /**
   * 可以覆写父类方法
   * public void doSomething(){
   *
   * }
   */
}

Composite树枝构件

树枝对象,作用是组合树枝节点和叶子节点形成一个树形结构

public class Composite extends Component {
  // 构建容器
  private ArrayList<Component> componentArrayList = new ArrayList<Component>();
  // 增加一个叶子构件或树枝构件
  public void add(Component component){
    this.componentArrayList.add(component);
  }
  
  // 删除一个叶子构件或树枝构件
  public void remove(Component component){
    this.componentArrayList.remove(component);
  }
  
  // 获取分支下的所有叶子构件和树枝构件
  public ArrayList<Component> getChildren(){
    return this.componentArrayList;
  }
}

场景类

负责树状结构的建立,并可以通过递归方式遍历整个树

public class client{
  public static void main(String[] args){
    // 创建一个根节点
    Composite root = new Composite();
    root.doSomething();
    // 创建一个树枝构件
    Composite branch = new Composite();
    // 创建一个叶子节点
    Leaf leaf = new Leaf();
    //建立整体
    root.add(branch);
    branch.add(leaf);
  }
  
  public static void display(Composite root){
    for(Component c : root.getChildren()){
      if (c instanceof Leaf){
        // 叶子节点
        c.doSomething();
      }else {
        //树枝节点
        display((Composite)c)
      }
    }
  }
}

WHY

优势

  • 高层模块调用简单
    • 一棵树形结构中所有节点都是Component,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码
  • 节点自由增加
    • 只要找到父节点,就可以增加树枝节点、叶子节点。
    • 非常容易扩展,符合开闭原则

劣势

与依赖倒置原则冲突,在场景类中直接使用了实现类,这在面向接口编程上很不恰当。

HOW

使用场景

  • 维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理等
    • 只要是树形结构,就考虑使用组合模式
    • 只要是体现局部和整体的关系时,而且这种关系还可能比较深,考虑使用组合模式
  • 从一个整体中能够独立出部分模块或功能的场景

《设计模式之禅》 第21章 组合模式