设计模式之禅【组合模式】

真刀实枪之组合模式

  • 从公司的人事架构谈起吧
    • 公司的组织架构
    • 从上图中可以分析出:
      1. 有分支的节点(树枝节点)
      2. 无分支的节点(叶子节点)
      3. 根节点(无父节点)
  • 有了树状结构图,再看看类图长啥样吧!
  • 这个类图是有缺陷的,等会儿继续修改,现在先看下这个不成熟类图的代码

    • IRoot

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public interface IRoot {
          // 得到总经理想要的信息
          public String getInfo();
      
          // 添加树枝节点
          public void add(IBranch banch);
      
          // 添加叶子节点
          public void add(ILeaf leaf);
      
          // 遍历节点
          public ArrayList getSubordinateInfo();
      }
      
    • Root

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public class Root implements IRoot {
          // 保存根节点下的树枝节点和叶子节点
          private ArrayList subordinateList = new ArrayList();
          // 根节点的名称
          private String name = "";
          // 根节点的职位
          private String position = "";
          // 根节点的薪水
          private int salary = 0;
      
          // 通过构造函数传递进来的总经理的信息
          Root(String name, String position, int salary) {
              super();
              this.name = name;
              this.position = position;
              this.salary = salary;
          }
      
          @Override
          public String getInfo() {
              String info = "";
              info += "根节点名称:" + this.name + ",根节点职位:" + this.position + ",根节点薪水:"
                      + this.salary;
              return info;
          }
      
          @Override
          public void add(IBranch branch) {
              this.subordinateList.add(branch);
          }
      
          @Override
          public void add(ILeaf leaf) {
              this.subordinateList.add(leaf);
          }
      
          @Override
          public ArrayList getSubordinateInfo() {
              return this.subordinateList;
          }
      
      }
      
    • IBranch

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public interface IBranch {
          // 得到信息
          public String getInfo();
      
          // 添加树枝节点
          public void add(IBranch banch);
      
          // 添加叶子节点
          public void add(ILeaf leaf);
      
          // 遍历节点
          public ArrayList getSubordinateInfo();
      }
      
    • Branch

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public class Branch implements IBranch {
      
          // 保存树枝节点下的树枝节点和叶子节点
          private ArrayList subordinateList = new ArrayList();
          // 树枝节点的名称
          private String name = "";
          // 树枝节点的职位
          private String position = "";
          // 树枝节点的薪水
          private int salary = 0;
      
          // 通过构造函数传递进来的树枝节点的信息
          Branch(String name, String position, int salary) {
              super();
              this.name = name;
              this.position = position;
              this.salary = salary;
          }
      
          @Override
          public String getInfo() {
              String info = "";
              info += "树枝节点名称:" + this.name + ",树枝节点职位:" + this.position + ",树枝节点薪水:"
                      + this.salary;
              return info;
          }
      
          @Override
          public void add(IBranch branch) {
              this.subordinateList.add(branch);
          }
      
          @Override
          public void add(ILeaf leaf) {
              this.subordinateList.add(leaf);
          }
      
          @Override
          public ArrayList getSubordinateInfo() {
              return this.subordinateList;
          }
      
      }
      
    • ILeaf

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public interface ILeaf {
          // 得到信息
          public String getInfo();
      
      }
      
    • Leaf

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public class Leaf implements ILeaf {
          // 叶子节点的名称
          private String name = "";
          // 叶子节点的职位
          private String position = "";
          // 叶子节点的薪水
          private int salary = 0;
      
          // 通过构造函数传递进来的叶子节点的信息
          Leaf(String name, String position, int salary) {
              super();
              this.name = name;
              this.position = position;
              this.salary = salary;
          }
      
          @Override
          public String getInfo() {
              String info = "";
              info += "叶子节点名称:" + this.name + ",叶子节点职位:" + this.position + ",叶子节点薪水:"
                      + this.salary;
              return info;
          }
      
      }
      
    • Client

      package com.peng.zh;
      
      import java.util.ArrayList;
      
      /**
       * @author kungfu~peng
       * @data 2017年11月24日
       * @description
       */
      public class Client {
      
          public static void main(String[] args) {
              // 先产生根节点
              IRoot ceo = new Root("王大麻子", "总经理", 100000);
              // 产生三个部门经理
              IBranch developDep = new Branch("刘大瘸子", "研发部门经理", 10000);
              IBranch salesDep = new Branch("马二拐子", "销售部门经理", 20000);
              IBranch financeDep = new Branch("赵三驼子", "财务部门经理", 30000);
              // 两个小组长
              IBranch firstDepGroup = new Branch("杨三也斜", "开发一组组长", 5000);
              IBranch secondDepGrooup = new Branch("吴大棒槌", "开发二组组长", 6000);
              // 研发部经理
              ILeaf zhengLaoLiu = new Leaf("郑老六", "研发部副总", 20000);
              // 员工
              ILeaf a = new Leaf("a", "开发人员", 2000);
              ILeaf b = new Leaf("b", "开发人员", 2000);
              ILeaf c = new Leaf("c", "开发人员", 2000);
              ILeaf d = new Leaf("d", "开发人员", 2000);
              ILeaf e = new Leaf("e", "开发人员", 2000);
              ILeaf f = new Leaf("f", "开发人员", 2000);
              ILeaf g = new Leaf("g", "开发人员", 2000);
              ILeaf h = new Leaf("h", "销售人员", 5000);
              ILeaf i = new Leaf("i", "销售人员", 4000);
              ILeaf j = new Leaf("j", "财务人员", 5000);
              ILeaf k = new Leaf("k", "ceo秘书人员", 8000);
              // 组装总经理
              ceo.add(developDep);
              ceo.add(salesDep);
              ceo.add(financeDep);
              ceo.add(k);
              // 组装研发部门
              developDep.add(firstDepGroup);
              developDep.add(secondDepGrooup);
              developDep.add(zhengLaoLiu);
              // 组装第一个开发小组
              firstDepGroup.add(a);
              firstDepGroup.add(c);
              firstDepGroup.add(d);
              // 组装第二个开发小组
              secondDepGrooup.add(e);
              secondDepGrooup.add(f);
              secondDepGrooup.add(g);
              // 组装销售部
              salesDep.add(h);
              salesDep.add(i);
              // 组装财务部
              financeDep.add(j);
              // 打印出来整个树形结构
              System.out.println(ceo.getInfo());
              getAllSubordinateInfo(ceo.getSubordinateInfo());
      
          }
      
          private static void getAllSubordinateInfo(ArrayList subordinateInfo) {
              int length = subordinateInfo.size();
              for (int i = 0; i < length; i++) {
                  Object s = subordinateInfo.get(i);
                  if (s instanceof Leaf) {
                      ILeaf employee = (ILeaf) s;
                      System.out.println(employee.getInfo());
                  } else {
                      IBranch branch = (IBranch) s;
                      System.out.println(branch.getInfo());
                      // 递归
                      getAllSubordinateInfo(branch.getSubordinateInfo());
                  }
              }
          }
      
      }
      
    • 执行结果
      根节点名称:王大麻子,根节点职位:总经理,根节点薪水:100000
      树枝节点名称:刘大瘸子,树枝节点职位:研发部门经理,树枝节点薪水:10000
      树枝节点名称:杨三也斜,树枝节点职位:开发一组组长,树枝节点薪水:5000
      叶子节点名称:a,叶子节点职位:开发人员,叶子节点薪水:2000
      叶子节点名称:c,叶子节点职位:开发人员,叶子节点薪水:2000
      叶子节点名称:d,叶子节点职位:开发人员,叶子节点薪水:2000
      树枝节点名称:吴大棒槌,树枝节点职位:开发二组组长,树枝节点薪水:6000
      叶子节点名称:e,叶子节点职位:开发人员,叶子节点薪水:2000
      叶子节点名称:f,叶子节点职位:开发人员,叶子节点薪水:2000
      叶子节点名称:g,叶子节点职位:开发人员,叶子节点薪水:2000
      叶子节点名称:郑老六,叶子节点职位:研发部副总,叶子节点薪水:20000
      树枝节点名称:马二拐子,树枝节点职位:销售部门经理,树枝节点薪水:20000
      叶子节点名称:h,叶子节点职位:销售人员,叶子节点薪水:5000
      叶子节点名称:i,叶子节点职位:销售人员,叶子节点薪水:4000
      树枝节点名称:赵三驼子,树枝节点职位:财务部门经理,树枝节点薪水:30000
      叶子节点名称:j,叶子节点职位:财务人员,叶子节点薪水:5000
      叶子节点名称:k,叶子节点职位:ceo秘书人员,叶子节点薪水:8000
      
  • 好,代码写完,把刚刚遗留的问题来找一下:
    1. getInfo每个接口都有,为什么不抽象出来?
    2. Root和Branch类有什么差别?
    3. 根节点本来就是树枝节点的一种,为什么要定义成两个接口?
    4. 若果我要增加一个任职期限,是不是所有的都要修改?
    5. 如果我要后续遍历,能做到吗?
  • 问题很多,一个一个解决

    1. 先说抽象问题,确实可以抽象出来,修改下类图

      1. 修改
      2. 仔细看这个图,能不能发现还有问题--想想接口的作用是什么?定义共性,既然是这样,那getInfo方法也可以封装啦,再继续修改
      3. 修改2
      4. 类图上增加了一个ICorp接口,它是公司所有员工的接口类
      5. 新类图的代码

        1. ICorp

          package zh2;
          
          /**
           * @author kungfu~peng
           * @data 2017年11月24日
           * @description
           */
          public interface ICorp {
              // 获取信息
              public String getInfo();
          }
          
        2. ILeaf

          package zh2;
          
          /**
           * @author kungfu~peng
           * @data 2017年11月24日
           * @description
           */
          public interface ILeaf extends ICorp {
          
          }
          
        3. Leaf

          package zh2;
          
          /**
           * @author kungfu~peng
           * @data 2017年11月24日
           * @description
           */
          public class Leaf implements ILeaf {
          
              // 叶子节点的名称
              private String name = "";
              // 叶子节点的职位
              private String position = "";
              // 叶子节点的薪水
              private int salary = 0;
          
              // 通过构造函数传递进来的叶子节点的信息
              Leaf(String name, String position, int salary) {
                  super();
                  this.name = name;
                  this.position = position;
                  this.salary = salary;
              }
          
              @Override
              public String getInfo() {
                  String info = "";
                  info += "叶子节点名称:" + this.name + ",叶子节点职位:" + this.position + ",叶子节点薪水:"
                          + this.salary;
                  return info;
              }
          
          }
          
        4. IBranch

          package zh2;
          
          import java.util.ArrayList;
          
          /**
           * @author kungfu~peng
           * @data 2017年11月24日
           * @description
           */
          public interface IBranch extends ICorp {
              // 增高增加小兵
              public void addSubordinate(ICorp corp);
          
              // 获得下属信息
              public ArrayList<ICorp> getSubordinate();
              // 删除下属--没用到,这里省略
          }
          
        5. Branch

          package zh2;
          
          import java.util.ArrayList;
          
          /**
           * @author kungfu~peng
           * @data 2017年11月24日
           * @description
           */
          public class Branch implements IBranch {
              // 保存节点下的树枝节点和叶子节点
              private ArrayList<ICorp> subordinateList = new ArrayList<ICorp>();
              // 树枝节点的名称
              private String name = "";
              // 树枝节点的职位
              private String position = "";
              // 树枝节点的薪水
              private int salary = 0;
          
              // 通过构造函数传递进来的树枝节点的信息
              Branch(String name, String position, int salary) {
                  super();
                  this.name = name;
                  this.position = position;
                  this.salary = salary;
              }
          
              @Override
              public String getInfo() {
                  String info = "";
                  info += "树枝节点名称:" + this.name + ",树枝节点职位:" + this.position + ",树枝节点薪水:"
                          + this.salary;
                  return info;
              }
          
              @Override
              public void addSubordinate(ICorp corp) {
                  this.subordinateList.add(corp);
              }
          
              @Override
              public ArrayList<ICorp> getSubordinate() {
                  return this.subordinateList;
              }
          
          }
          
        6. Client

          package zh2;
          
          import java.util.ArrayList;
          
          /**
           * @author kungfu~peng
           * @data 2017年11月24日
           * @description
           */
          public class Client {
              public static void main(String[] args) {
          
                  // 先产生根节点
                  Branch ceo = new Branch("王大麻子", "总经理", 100000);
                  // 产生三个部门经理
                  IBranch developDep = new Branch("刘大瘸子", "研发部门经理", 10000);
                  IBranch salesDep = new Branch("马二拐子", "销售部门经理", 20000);
                  IBranch financeDep = new Branch("赵三驼子", "财务部门经理", 30000);
                  // 两个小组长
                  IBranch firstDepGroup = new Branch("杨三也斜", "开发一组组长", 5000);
                  IBranch secondDepGrooup = new Branch("吴大棒槌", "开发二组组长", 6000);
                  // 研发部经理
                  ILeaf zhengLaoLiu = new Leaf("郑老六", "研发部副总", 20000);
                  // 员工
                  ILeaf a = new Leaf("a", "开发人员", 2000);
                  ILeaf b = new Leaf("b", "开发人员", 2000);
                  ILeaf c = new Leaf("c", "开发人员", 2000);
                  ILeaf d = new Leaf("d", "开发人员", 2000);
                  ILeaf e = new Leaf("e", "开发人员", 2000);
                  ILeaf f = new Leaf("f", "开发人员", 2000);
                  ILeaf g = new Leaf("g", "开发人员", 2000);
                  ILeaf h = new Leaf("h", "销售人员", 5000);
                  ILeaf i = new Leaf("i", "销售人员", 4000);
                  ILeaf j = new Leaf("j", "财务人员", 5000);
                  ILeaf k = new Leaf("k", "ceo秘书人员", 8000);
                  // 组装总经理
                  ceo.addSubordinate(developDep);
                  ceo.addSubordinate(salesDep);
                  ceo.addSubordinate(financeDep);
                  ceo.addSubordinate(k);
                  // 组装研发部门
                  developDep.addSubordinate(firstDepGroup);
                  developDep.addSubordinate(secondDepGrooup);
                  developDep.addSubordinate(zhengLaoLiu);
                  // 组装第一个开发小组
                  firstDepGroup.addSubordinate(a);
                  firstDepGroup.addSubordinate(c);
                  firstDepGroup.addSubordinate(d);
                  // 组装第二个开发小组
                  secondDepGrooup.addSubordinate(e);
                  secondDepGrooup.addSubordinate(f);
                  secondDepGrooup.addSubordinate(g);
                  // 组装销售部
                  salesDep.addSubordinate(h);
                  salesDep.addSubordinate(i);
                  // 组装财务部
                  financeDep.addSubordinate(j);
                  // 打印出来整个树形结构
                  System.out.println(ceo.getInfo());
                  getAllSubordinateInfo(ceo.getSubordinate());
          
              }
          
              private static void getAllSubordinateInfo(ArrayList subordinateInfo) {
                  int length = subordinateInfo.size();
                  for (int i = 0; i < length; i++) {
                      Object s = subordinateInfo.get(i);
                      if (s instanceof Leaf) {
                          ILeaf employee = (ILeaf) s;
                          System.out.println(employee.getInfo());
                      } else {
                          IBranch branch = (IBranch) s;
                          System.out.println(branch.getInfo());
                          // 递归
                          getAllSubordinateInfo(branch.getSubordinate());
                      }
                  }
              }
          }
          
        7. 执行结果
          树枝节点名称:王大麻子,树枝节点职位:总经理,树枝节点薪水:100000
          树枝节点名称:刘大瘸子,树枝节点职位:研发部门经理,树枝节点薪水:10000
          树枝节点名称:杨三也斜,树枝节点职位:开发一组组长,树枝节点薪水:5000
          叶子节点名称:a,叶子节点职位:开发人员,叶子节点薪水:2000
          叶子节点名称:c,叶子节点职位:开发人员,叶子节点薪水:2000
          叶子节点名称:d,叶子节点职位:开发人员,叶子节点薪水:2000
          树枝节点名称:吴大棒槌,树枝节点职位:开发二组组长,树枝节点薪水:6000
          叶子节点名称:e,叶子节点职位:开发人员,叶子节点薪水:2000
          叶子节点名称:f,叶子节点职位:开发人员,叶子节点薪水:2000
          叶子节点名称:g,叶子节点职位:开发人员,叶子节点薪水:2000
          叶子节点名称:郑老六,叶子节点职位:研发部副总,叶子节点薪水:20000
          树枝节点名称:马二拐子,树枝节点职位:销售部门经理,树枝节点薪水:20000
          叶子节点名称:h,叶子节点职位:销售人员,叶子节点薪水:5000
          叶子节点名称:i,叶子节点职位:销售人员,叶子节点薪水:4000
          树枝节点名称:赵三驼子,树枝节点职位:财务部门经理,树枝节点薪水:30000
          叶子节点名称:j,叶子节点职位:财务人员,叶子节点薪水:5000
          叶子节点名称:k,叶子节点职位:ceo秘书人员,叶子节点薪水:8000
          
      6. getInfo方法都有,是不是可以继续优化,把ICorp接口变化成一个抽象类,将getInfo方法在抽象类中实现

        1. 再次修改类图
        2. 代码实现

          1. Corp

            package zh3;
            
            
            /**
             * @author kungfu~peng
             * @data 2017年11月25日
             * @description
             */
            public abstract class Corp {
                // 树枝节点的名称
                private String name = "";
                // 树枝节点的职位
                private String position = "";
                // 树枝节点的薪水
                private int salary = 0;
            
                // 通过构造函数传递进来的树枝节点的信息
                Corp(String name, String position, int salary) {
                    this.name = name;
                    this.position = position;
                    this.salary = salary;
                }
            
                public String getInfo() {
                    String info = "";
                    info += "树枝节点名称:" + this.name + ",树枝节点职位:" + this.position + ",树枝节点薪水:"
                            + this.salary;
                    return info;
                }
            
            }
            
          2. Branch

            package zh3;
            
            import java.util.ArrayList;
            
            import zh2.ICorp;
            
            /**
             * @author kungfu~peng
             * @data 2017年11月25日
             * @description
             */
            public class Branch extends Corp {
                // 保存节点下的树枝节点和叶子节点
                private ArrayList<Corp> subordinateList = new ArrayList<Corp>();
            
                Branch(String name, String position, int salary) {
                    super(name, position, salary);
                }
            
                // 增加下属
                public void addSubordinate(Corp corp) {
                    this.subordinateList.add(corp);
                }
            
                // 我有哪些下属
                public ArrayList<Corp> getSubordinate() {
                    return this.subordinateList;
                }
            }
            
          3. Leaf

            package zh3;
            
            /**
             * @author kungfu~peng
             * @data 2017年11月25日
             * @description
             */
            public class Leaf extends Corp {
            
                Leaf(String name, String position, int salary) {
                    super(name, position, salary);
                }
            
            }
            
          4. Client

            package zh3;
            
            import java.util.ArrayList;
            
            /**
             * @author kungfu~peng
             * @data 2017年11月25日
             * @description
             */
            public class Client {
            
                public static void main(String[] args) {
            
                    // 先产生根节点
                    Branch ceo = new Branch("王大麻子", "总经理", 100000);
                    // 产生三个部门经理
                    Branch developDep = new Branch("刘大瘸子", "研发部门经理", 10000);
                    Branch salesDep = new Branch("马二拐子", "销售部门经理", 20000);
                    Branch financeDep = new Branch("赵三驼子", "财务部门经理", 30000);
                    // 两个小组长
                    Branch firstDepGroup = new Branch("杨三也斜", "开发一组组长", 5000);
                    Branch secondDepGrooup = new Branch("吴大棒槌", "开发二组组长", 6000);
                    // 研发部经理
                    Leaf zhengLaoLiu = new Leaf("郑老六", "研发部副总", 20000);
                    // 员工
                    Leaf a = new Leaf("a", "开发人员", 2000);
                    Leaf b = new Leaf("b", "开发人员", 2000);
                    Leaf c = new Leaf("c", "开发人员", 2000);
                    Leaf d = new Leaf("d", "开发人员", 2000);
                    Leaf e = new Leaf("e", "开发人员", 2000);
                    Leaf f = new Leaf("f", "开发人员", 2000);
                    Leaf g = new Leaf("g", "开发人员", 2000);
                    Leaf h = new Leaf("h", "销售人员", 5000);
                    Leaf i = new Leaf("i", "销售人员", 4000);
                    Leaf j = new Leaf("j", "财务人员", 5000);
                    Leaf k = new Leaf("k", "ceo秘书人员", 8000);
                    // 组装总经理
                    ceo.addSubordinate(developDep);
                    ceo.addSubordinate(salesDep);
                    ceo.addSubordinate(financeDep);
                    ceo.addSubordinate(k);
                    // 组装研发部门
                    developDep.addSubordinate(firstDepGroup);
                    developDep.addSubordinate(secondDepGrooup);
                    developDep.addSubordinate(zhengLaoLiu);
                    // 组装第一个开发小组
                    firstDepGroup.addSubordinate(a);
                    firstDepGroup.addSubordinate(c);
                    firstDepGroup.addSubordinate(d);
                    // 组装第二个开发小组
                    secondDepGrooup.addSubordinate(e);
                    secondDepGrooup.addSubordinate(f);
                    secondDepGrooup.addSubordinate(g);
                    // 组装销售部
                    salesDep.addSubordinate(h);
                    salesDep.addSubordinate(i);
                    // 组装财务部
                    financeDep.addSubordinate(j);
                    // 打印出来整个树形结构
                    System.out.println(ceo.getInfo());
                    getAllSubordinateInfo(ceo.getSubordinate());
            
                }
            
                private static void getAllSubordinateInfo(ArrayList subordinateInfo) {
                    int length = subordinateInfo.size();
                    for (int i = 0; i < length; i++) {
                        Object s = subordinateInfo.get(i);
                        if (s instanceof Leaf) {
                            Leaf employee = (Leaf) s;
                            System.out.println(employee.getInfo());
                        } else {
                            Branch branch = (Branch) s;
                            System.out.println(branch.getInfo());
                            // 递归
                            getAllSubordinateInfo(branch.getSubordinate());
                        }
                    }
                }
            }
            
          5. 执行结果
            树枝节点名称:王大麻子,树枝节点职位:总经理,树枝节点薪水:100000
            树枝节点名称:刘大瘸子,树枝节点职位:研发部门经理,树枝节点薪水:10000
            树枝节点名称:杨三也斜,树枝节点职位:开发一组组长,树枝节点薪水:5000
            树枝节点名称:a,树枝节点职位:开发人员,树枝节点薪水:2000
            树枝节点名称:c,树枝节点职位:开发人员,树枝节点薪水:2000
            树枝节点名称:d,树枝节点职位:开发人员,树枝节点薪水:2000
            树枝节点名称:吴大棒槌,树枝节点职位:开发二组组长,树枝节点薪水:6000
            树枝节点名称:e,树枝节点职位:开发人员,树枝节点薪水:2000
            树枝节点名称:f,树枝节点职位:开发人员,树枝节点薪水:2000
            树枝节点名称:g,树枝节点职位:开发人员,树枝节点薪水:2000
            树枝节点名称:郑老六,树枝节点职位:研发部副总,树枝节点薪水:20000
            树枝节点名称:马二拐子,树枝节点职位:销售部门经理,树枝节点薪水:20000
            树枝节点名称:h,树枝节点职位:销售人员,树枝节点薪水:5000
            树枝节点名称:i,树枝节点职位:销售人员,树枝节点薪水:4000
            树枝节点名称:赵三驼子,树枝节点职位:财务部门经理,树枝节点薪水:30000
            树枝节点名称:j,树枝节点职位:财务人员,树枝节点薪水:5000
            树枝节点名称:k,树枝节点职位:ceo秘书人员,树枝节点薪水:8000
            

组合模式的定义

  • Composite Pattern
  • 也叫合成模式或整体-部分模式,主要是描述部分与整体的关系
  • Compose objects into tree structures to represent part-whole hirearchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构,以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性)

通用类图

  • 几个角色
    1. Component抽象构建角色:可以定义属性和方法
    2. Leaf叶子构件:遍历的最小单位
    3. Composite树枝构件:中间节点或根节点
  • 通用代码这里不再赘述

组合模式的应用

  • 组合模式的优点
    1. 高层模块调用简单
    2. 节点自由增加
  • 组合模式的缺点
    1. 场景类直接使用了树叶节点和树枝节点,这在面向接口编程上是很不恰当的,与依赖原则冲突
  • 使用场景
    1. 维护和展示“部分-整体”关系的场景--树形菜单、文件和文件夹管理
    2. 从一个整体中能够独立出部分模块或功能的场景

组合模式的注意事项

  • 只要是树形结构就考虑组合模式--体现“部分-整体”关系的时候

组合模式的扩展

  • 安全模式的组合模式【之前写的就是】
  • 透明的组合模式
    • 类图
      • 透明模式就是将组合使用的方法放到抽象类中,不管是叶子还是树枝都有这个方法,通过判断getChild的返回值确定是叶子节点还是树枝节点,如果处理不当,运行期间会出问题
      • 不是很建议这种方式
      • 代码--注意叶子节点的add方法的重写--抛出“不支持请求异常”即可--throw new UnsupportedOperationException();
  • 组合模式的遍历
    1. 上到下【上面的已经实现】
    2. 下到上【增加parent】
      1. 类图
        1. ​​​​​​​
      2. 代码(看了这么多,自己动手试一试)

最佳实践

  • 页面结构【top,center(left,right),bottom】
  • JavaScript
  • xml
  • 血缘关系

声明

  • 摘自秦小波《设计模式之禅》第2版;
  • 仅供学习,严禁商业用途;
  • 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘风御浪云帆之上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值