什么是组合模式

组合模式在维基百科上的的定义是:

In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to “compose” objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

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

组合模式的结构如下:

抽象构件抽象了叶子构件和容器构件的行为,客户端面向抽象构件编程,这样可以统一对待叶子构件和容器构件。叶子构件和容器构件行为的实现方现有所不同,可以在具体类中重写抽象类的方法。

一个组合模式实例

如公司的组织架构。公司下面设有多个不同部门,Hr部门和Dev部门。公司下面还可以有子公司,而子公司下面又设有自己的Hr部门和Dev部门。在这里公司为容器构件,部门为叶子构件。现在需要向其中的某个公司或子公司发通知(包括公司下面的部门和公司下面子公司的部门)。这时就可以使用组合模式。

透明组合模式和安全组合模式

组合模式有两种方式,透明组合模式和安全组合模式。它们的区别是容器构件特有而叶子构件没有的特性定义在抽件构件中还是定义在叶子构件中。

透明组合模式:

安全组合模式:

透明组合模式在编码时可以统一面向抽象构件编码,不需要区分是叶子构件还是容器构件。但是叶子构件是不具有add()和remove()特性的,叶子构件中的这些方法必须抛出异常或做出说明,否则调用者调用时会出错。

安全组合模式在编码时必须区分是叶子构件还是容器构件。针对容器构件进行add()和remove()操作。

一个透明组合模式实例代码

public abstract class AbstractUnit {
    public abstract void sendNotify();
    public void add(AbstractUnit unit){
        System.out.println("Not Support");
    }
    public void remove(AbstractUnit unit){
        System.out.println("Not Support");
    }
}
import java.util.ArrayList;
import java.util.List;

public class Company extends AbstractUnit {
    List<AbstractUnit> list = new ArrayList<>();

    private String name;
    public Company(String name){
        this.name = name;
    }

    @Override
    public void sendNotify() {
        System.out.println("Send ["+this.name+"] Company Notify");
        for (AbstractUnit unit:list){
            unit.sendNotify();
        }
    }

    public void add(AbstractUnit unit){
        this.list.add(unit);
    }
}
public class Dev extends AbstractUnit {

    private String name;

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

    @Override
    public void sendNotify() {
        System.out.println("Send [" + this.name + "] Dev Notify");
    }
}
public class Hr extends AbstractUnit {

    private String name;

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

    @Override
    public void sendNotify() {
        System.out.println("Send [" + this.name + "] HR Notify");
    }
}
public class Client {

    public static void main(String[] args){
        AbstractUnit hr1,hr2,dev1,dev2,dev3,company1,company2;

        hr1 = new Hr("Jon");
        hr2 = new Hr("Snow");

        dev1 = new Dev("ZhangJiang");
        dev2 = new Dev("GuangGu");
        dev3 = new Dev("KeXing");

        company1 = new Company("QQ");
        company2 = new Company("WeChat");

        company2.add(hr1);
        company2.add(dev3);
        company1.add(hr2);
        company1.add(dev1);
        company1.add(dev2);
        company1.add(company2);

        company1.sendNotify();
    }
}

(完)