JAVA23种设计模式之组合模式

  1. 组合模式
    组合模式又叫部分整体模式,适用于把一组相似的对象当做一个单一的对象进行处理,组合模式是以树形结构来表示部分-整体的层次结构。组合模式是用户可以按照相同的方法去处理单个对象和组合对象。
  2. 组合式示意图:组合模式在使用上又分为两种,一种是透明组合模式安全组合模式。类图分别如下:
    2.1. 透明组合模式 :抽象的根节点声明了管理叶节点的方法以及业务方法,客户端可以一致对待所有对象。但是由于叶节点不可能管理子节点,如果处理方式不对,容易出错。
    透明组合模式
    2.2. 安全组合模式:抽象根节点只声明了业务方法,具体子节点的管理方法有自己声明。因为叶节点没有管理子节点的方法,相对来说是安全的,这就导致了叶子节点和node节点的结构不一致,因此需要区别对待。
    安全组合模式

3.组合模式中所包含的角色

  • 抽象根节点角色: 可以是接口或者是抽象类,为叶子和node声明结构,在该角色可以定义leaf和node子类所共有的方法,也可以定义管理子节点的方法。
  • 叶子节点:遍历的最小单位,其下面就再也没有任何分支
  • 树枝节点:非遍历的最小单位,其中可以包含一个或者多个叶节点或树枝节点,可以递归调用叶节点的业务方法。

4.组合模式实例代码
示例代码:
场景:末公司扩大组织结构,新增了多个一级部门和二级部门,假定方便管理,该公司最小部门为二级部门。现在需求是使用组合模式,打印出其所有部门。(这里很明显二级部门是叶子节点,一级部门是树枝节点)
根节点:

public abstract class  Department {
    /**
     * 添加方法
     * @param department
     */
     abstract void add(Department department);
    /**
     * 移除方法
     * @param department
     */
     abstract void remove(Department department);
    /**
     * 获取子节点
     * @return
     */
     abstract ArrayList<Department> getChild();
    /**
     * 打印
     */
    abstract void print();
}

树枝节点:

public class FirstDepartment extends Department {
    //用于存储叶子节点
    ArrayList<Department> departments = new ArrayList<Department>();
    private String name;
    public FirstDepartment(ArrayList<Department> departments,String name) {
        this.departments = departments;
        this.name = name;
    }
    @Override
    void add(Department department) {
              departments.add(department);
    }
    @Override
    void remove(Department department) {
          if (departments.contains(department)){
                  departments.remove(department);
           }else {
              System.out.println("不存在该部门,无法移除");
          }
    }
    @Override
     ArrayList<Department> getChild() {
           return departments;
    }
    @Override
    void print() {
        System.out.println("一级部门>>>>"+this.name);
           Iterator iterator =  departments.iterator();
           while (iterator.hasNext()){
               ((Department)iterator.next()).print();
           }
    }
}

树叶节点:

public class SecondDepartment extends Department {
    private String name;
    public SecondDepartment(String name) {
        this.name = name;
    }
    @Override
    void add(Department department) {
        System.out.println("已经是叶子节点无法添加子节点!");
    }
    @Override
    void remove(Department department) {
        System.out.println("已经是叶子节点无法移除子节点!");
    }
    @Override
    ArrayList<Department> getChild() {
        System.out.println("已经是叶子节点无多余的子节点!");
        return null;
    }
    @Override
    void print() {
        System.out.println("叶子节点>>>>>>>>>>"+name);
    }
}

测试主方法:

public class Main {
    public static void main(String[] args) {
        ArrayList hr = new ArrayList();
        Department leaf = new SecondDepartment("人力资源业务一部");
        Department leaf1 = new SecondDepartment("人力资源业务2部");
        hr.add(leaf);
        hr.add(leaf1);
        Department departmentForHr = new FirstDepartment(hr,"人力资源部");
        departmentForHr.print();
        ArrayList pmo = new ArrayList();
        Department leaf2 = new SecondDepartment("PMO业务一部");
        Department leaf3 = new SecondDepartment("PMO业务一部");
        pmo.add(leaf2);
        pmo.add(leaf3);
        Department departmentForPMO = new FirstDepartment(pmo,"PMO");
        departmentForHr.print();

    }
}
  1. 组合模式的优缺点

优点:

  • 可以清楚的定义树形的复杂对象。表示对象的全部层次或者部分层次
  • 可以使用单一的对象,而不必关心处理的对象是叶子节点还是树枝节点,简化客户端代码。
  • 便于增加叶子节点和树枝节点,而不需要修改原有代码。
  • 通过叶子对象和容器对象的递归组合可以形成复杂的树形机构,但对树形结构的控制却很简单。

缺点:

  • 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
  • 难以对容器中的构件类型限制。
发布了62 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/system_obj/article/details/87998484