好用的设计模式 -- 责任链

2021-02-02  本文已影响0人  瑞瑞余之

责任链是一种日常开发常用的设计模式,这里之所以说它好用,是因为责任链的形式很贴合面向过程的开发思路,易于理解,同时链式也利于开发者归纳功能,管理代码。

其实这种设计模式很容易理解,我们都知道链表(单向)的数据结构:

class Node {
    
    private Node next;
    private Object value;

    ……(构造方法)
}

理解链表就很容易理解责任链:责任链是由多个执行对象构成的,它们都有两个共同的属性:一是“next”,表示下一个执行对象;二是执行方法,也就是说当前对象需要进行的操作方法。既然所有执行对象都有这两个共同的属性,我们就可以抽象出一个抽象类,它有一个基础属性“next”,和抽象方法:“handleWork”:

public abstract class Handler {
    
    protected Handler next;

    abstract protected String handleWork(Object obj);
}

看起来Node和Handler可以对应上,只是说Node没有具体的行为方法,而Handler有基础方法。
有以上的基础知识,咱们来实现这样一个场景:
咱们有一个收入证明需要申请公司盖章,这个过程中需要小组领导,部门主管,公司财务进行审批。只有顺次通过之后,才可以最终获得公章。这里我们可以按照责任链的思路进行实现:

1. 创建证明的抽象类 Certification.java,虽然是个示例,但是我们还是按照真实设计出发,证明的类型可能有很多,比如收入证明,结婚证明,核算证明等等,咱们抽象出一个证明类,然后创建它的子类IncomeCertification.java。

public abstract class Certification {

    protected String name;

    /**
     * 1 - 收入证明
     * 2 - 核算证明
     * 3 - 结婚证明
     */
    private Integer type;

    private String owner;

    //... get and set methods
}
public class IncomeCertification extends Certification {

    private Integer income;

   //... get and set methods
}

ok!entity定义完成,可以看到,收入证明有4个属性,其中名称、类型、拥有者是继承自父类,具体收入是个性化属性。现在咱们定义责任链执行对象的基类:

public abstract class Handler {

    protected Handler next;

    abstract protected boolean processCertification(Certification cert);
}

对于小组领导来说,他需要确认该申请人属于自己团队:

public class GroupLeaderHandler extends Handler {

    private static List<String> teamMember = new ArrayList<String>();

    static {
        teamMember.add("ruiruiyuzhi");
        teamMember.add("zhangsan");
    }

    @Override
    protected boolean processCertification(Certification cert) {
        if (teamMember.contains(cert.getOwner())) {
            return this.next.processCertification(cert);
        }
        return false;
    }
}

对于部门领导来说,他需要确认收入无误:

public class DepartmentLeaderHandler extends Handler {

    private static final Integer INCOME_TYPE = 1;
    private static final Integer INCOME = 1000;

    @Override
    protected boolean processCertification(Certification cert) {
        IncomeCertification incomeCert = (IncomeCertification) cert;
        if (INCOME_TYPE.equals(cert.getType()) && INCOME.equals(incomeCert.getIncome())) {
            return this.next.processCertification(cert);
        }
        return false;
    }
}

财务人员判断申请类型为已有类型,则审批通过:

public class FinancialHandler extends Handler {

    private static List<Integer> certType = new ArrayList<Integer>();

    static {
        certType.add(1);
        certType.add(2);
        certType.add(3);
    }
    
    @Override
    protected boolean processCertification(Certification cert) {
        return certType.contains(cert.getType()); 
    }
}

到目前为止我们准备好了各个责任链环节的执行对象,进而需要将其串成链,这个过程跟链表的初始化相似:

    public static void main(String[] args) {
        //1.初始化责任链
        GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
        DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
        FinancialHandler financialHandler = new FinancialHandler();
        groupLeaderHandler.setNext(departmentLeaderHandler);
        departmentLeaderHandler.setNext(financialHandler);
                                             ……

其次,构建待审批的证明对象:

    public static void main(String[] args) {
        //1.初始化责任链
        GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
        DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
        FinancialHandler financialHandler = new FinancialHandler();
        groupLeaderHandler.setNext(departmentLeaderHandler);
        departmentLeaderHandler.setNext(financialHandler);
        //2.构建证明对象
        IncomeCertification myIncomeCert = new IncomeCertification();
        myIncomeCert.setIncome(1000);
        myIncomeCert.setName("income certification");
        myIncomeCert.setOwner("ruiruiyuzhi");
        myIncomeCert.setType(1);

这时候我们就需要进入责任链开始审核了,但是入口在哪呢?当然,你可以强行把GroupLeaderHandler中加入一个public方法,作为入口,但是这样做扩展性不好,比方说这条审核的链条有新环节加入,或者有环节精简,改变了入口,岂不是需要重新编写入口?
其实我们可以把入口放在Handler中,这个方法意味着从当前环节开始,往下走,这样我们只需要根据业务需要改变入口对象即可:

public abstract class Handler {

    protected Handler next;

    abstract protected boolean processCertification(Certification cert);

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }
    //从当前结点开始,往下走
    public boolean processFromCurrentHandler(Certification cert) {
        return this.processCertification(cert);
    }
}

这样,我们在Main方法中去测试整个流程可以发现,责任链的形式跑通了。

public class MainApplication {

    public static void main(String[] args) {
        GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
        DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
        FinancialHandler financialHandler = new FinancialHandler();
        groupLeaderHandler.setNext(departmentLeaderHandler);
        departmentLeaderHandler.setNext(financialHandler);

        IncomeCertification myIncomeCert = new IncomeCertification();
        myIncomeCert.setIncome(1000);
        myIncomeCert.setName("income certification");
        myIncomeCert.setOwner("ruiruiyuzhi");
        myIncomeCert.setType(1);
        boolean isPass = groupLeaderHandler.processFromCurrentHandler(myIncomeCert);
        if (isPass) {
            System.out.println("get the certification");
        } else {
            System.out.println("reject");
        }
    }
}
image.png
上一篇下一篇

猜你喜欢

热点阅读