20. 组合模式

定义

组合模式(Composite Pattern):组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式。

通俗理解

生活中有许多树型结构的东西,例如一家公司的员工关系,由董事长管理CEO、COO、CTO、CFO等等,又由CTO管理研发部门,测试部门,运维部门等等,每一个部门也有部门老大,部门当中也有项目组,项目组中有组长,组长还管理着组员;文件夹的目录也是这样的一个结构,文件夹中有文件夹,也有文件,他们按照树型的结构一直往下延伸。

就用员工组织做例子。按一般的想法设计这一个树形的系统,我们会认为,部门是一个是一个对象,而员工是另外一个对象。对于部门而言,我们能够显示他的基本信息,能够添加部门(子部门)、添加部门(子部门)、添加员工、删除员工,而对于个人而言,我们只能够显示基本信息,对于添加员工和删除员工的操作是不存在的。

把他们割裂开来会出现什么问题?第一:访问部门和访问个人需要区分两个不同的接口,而显示基本信息的是部门和个人都通用的方法却没有提供出来。第二:造成部门会很复杂,在部门当中,需要写添加部门的方法,同时也需要写添加员工的方法;第三:不方便扩展,如果我部门是具有不同的性质的,例如在信息部门中添加研发部门,运维部门等,研发和运维有不同的性质,那么我们需要在信息部门当中改相关的方法,这就违背了开闭原则。

换一个想法,把个人和部门都看成是一个一样的东西,部门和个人都有显示信息的方法,那么我们就把他们提取出来,做成公用的方法。而关于添加个人的方法,由于个人不可能再添加了,所以当用户调用这个方法的时候,就抛出异常。这样的设计,就能够整体对待部门和个人了。

示例

渣渣程序

员工信息

public class Staff {
    private String name;
    public Staff(String name) {
        this.name = name;
    }
    public void info() {
        System.out.println(name);
    }
}

部门

public class Department {
    public String name;
    public List staffList = new ArrayList<>();
    public List departmentList = new ArrayList<>();
    public Department(String name) {
        this.name = name;
    }
    public void addStaff(Staff staff) {
        staffList.add(staff);
    }
    public void removeStaff(Staff staff) {
        staffList.remove(staff);
    }
    public void addDepartment(Department department) {
        departmentList.add(department);
    }
    public void removeDepartment(Department department) {
        departmentList.remove(department);
    }
    public void info() {
        System.out.println(name);
    }
}

入口

public class Main {
    public static void main(String[] args) {
        Department infoDep = new Department("信息部门");
        Department devDep = new Department("研发部门");
        Department opsDep = new Department("运维部门");
        infoDep.addDepartment(devDep);
        infoDep.addDepartment(opsDep);
        Staff ccc = new Staff("ccc");
        Staff ddd = new Staff("ddd");
        devDep.addStaff(ccc);
        devDep.addStaff(ddd);
        Staff eee = new Staff("eee");
        Staff fff = new Staff("fff");
        opsDep.addStaff(eee);
        opsDep.addStaff(fff);
        new Main().info(infoDep);
    }
    public void info(Department department) {
        department.info();
        for (Staff staff : department.staffList) {
            staff.info();
        }
        for(Department department1 : department.departmentList) {
            info(department1);
        }
    }
}
/**
* 信息部门
* 研发部门
* ccc
* ddd
* 运维部门
* eee
* fff
*/

优化

类图

20. 组合模式_第1张图片

程序

部门和员工的统一抽象类

public abstract class DepartmentStaff {
    public abstract void info();
    public boolean isDepartment() {
        return false;
    }
    public void add(DepartmentStaff departmentStaff) {
        System.out.println("系统发生错误");
    }
    public void remove(DepartmentStaff departmentStaff) {
        System.out.println("系统发生错误");
    }
    public List getChild() {
        System.out.println("系统发生错误");
        return null;
    }
}

部门

public class Department extends DepartmentStaff {
    private List children;
    private String name;

    public Department(String name) {
        this.name = name;
        children = new ArrayList<>();
    }

    @Override
    public void info() {
        System.out.println("部门:"+name);
        for(DepartmentStaff departmentStaff : getChild()) {
            departmentStaff.info();
        }
    }

    @Override
    public void add(DepartmentStaff departmentStaff) {
        getChild().add(departmentStaff);
    }

    @Override
    public void remove(DepartmentStaff departmentStaff) {
        getChild().remove(departmentStaff);
    }

    @Override
    public List getChild() {
        return children;
    }

    public void setChildren(List children) {
        this.children = children;
    }
}

员工

public class Staff extends DepartmentStaff {
    private String name;

    public Staff(String name) {
        this.name = name;
    }

    @Override
    public void info() {
        System.out.println("员工:"+name);
    }
}

入口

public class Main {
    public static void main(String[] args) {
        DepartmentStaff d1 = new Department("d1");
        DepartmentStaff d1_1 = new Department("d1_1");

        DepartmentStaff s1 = new Staff("s1");
        d1_1.add(s1);
        d1.add(d1_1);
        d1.info();
    }
}
//部门:d1
//部门:d1_1
//员工:s1

优点

  1. 整体和部分都是一样的,调用方不用关心处理的是整体还是部分;
  2. 节点层次容易添加。

缺点

  1. 直接使用了实现,违反依赖倒置原则。

应用场景

  1. 整体和部分希望一致对待的;
  2. 维护整体与部分的关系的;

程序

e20_composite_pattern|给我star

吐槽

一脸懵逼

https://www.jianshu.com/p/af20a0fff472

你可能感兴趣的:(20. 组合模式)