美文网首页
好用的设计模式 -- 责任链

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

作者: 瑞瑞余之 | 来源:发表于2021-02-02 18:38 被阅读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

    相关文章

      网友评论

          本文标题:好用的设计模式 -- 责任链

          本文链接:https://www.haomeiwen.com/subject/ybpytltx.html