设计模式|设计模式-职责链模式

OA系统采购审批需求
【设计模式|设计模式-职责链模式】学校oa系统的采购审批项目:需求是

  1. 采购员采购教学器材
  2. 如果金额小于等于5000,由教学主任审批
  3. 如果金额小于等于10000,由院长审批
  4. 如果金额小于等于30000,由副校长审批
  5. 如果金额超过30000以上,由校长审批
传统方式解决OA系统审批问题分析
  1. 传统方式是:接收到一个采购请求之后,根据采购金额调用对应的Approver(审批人)完成审批
  2. 传统方式的问题分析:客户端到这里会使用到分支判断来对不同的采购请求处理,这样就存在如下问题
    • 如果各个级别的人员审批金额发生变化,在客户端的也需要变化
    • 客户端必须明确的知道 有多少审批级别和访问
  3. 这样对一个采购请求进行处理和approver(审批人)就存在强耦合关系,不利于代码的扩展和维护
  4. 解决方案-》责任链模式
职责链模式基本介绍
  1. 职责链模式又叫责任链模式,为请求创建了一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦
  2. 责任链模式通常每个接收者都包含另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传递给下一个接收者,依次类推
  3. 这种设计模式属于行为型模式
    设计模式|设计模式-职责链模式
    文章图片

    责任链模式 :使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条链,并沿着这条链,传递该请求,直到有一个对象处理它为止
对原理类图的说明(责任链模式的角色及职责)
  1. handler:抽象的处理者,定义了一个处理请求的接口,同时含有另外两个handler
  2. concreteHandlerA,B是具体的处理者,处理它自己负责的请求,可以访问它的后继者(即下一个处理者),如果可以处理当前请求,则处理,否则就将该请求交给后继者去处理,从而形成一个职责链
  3. request,含有很多属性,表示一个请求
    设计模式|设计模式-职责链模式
    文章图片
代码示例如下:
package com.cxf.feifei; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class PurchaseRequest {private double money; }

package com.cxf.feifei; public abstract class Approver {private Approver approver; private String name; public Approver(String name){this.name=name; } //下一个处理者 public void setApprover(Approver approver) {this.approver = approver; } public String getName() {return name; } public Approver getApprover() {return approver; } //处理审批请求的方法,得到一个请求,处理是具体实现子类完成 public abstractvoid processRequest(PurchaseRequest request); }

package com.cxf.feifei; public class DepartmentApprover extendsApprover {public DepartmentApprover(String name){super(name); } @Override public void processRequest(PurchaseRequest request) {if(request.getMoney()<=5000){System.out.println("该"+request.getMoney()+"的请求已经被"+getName()+"处理啦"); }else{getApprover().processRequest(request); } } }

package com.cxf.feifei; public class CollegeApprover extendsApprover {public CollegeApprover(String name){super(name); } @Override public void processRequest(PurchaseRequest request) {if(request.getMoney()<=20000 && request.getMoney()>5000){System.out.println("该"+request.getMoney()+"的请求已经被"+getName()+"处理啦"); }else{getApprover().processRequest(request); } } }

package com.cxf.feifei; public class ViceSchoolMasterApprover extendsApprover {public ViceSchoolMasterApprover(String name){super(name); } @Override public void processRequest(PurchaseRequest request) {if(request.getMoney()<=30000 && request.getMoney()>20000){System.out.println("该"+request.getMoney()+"的请求已经被"+getName()+"处理啦"); }else{getApprover().processRequest(request); } } }

package com.cxf.feifei; public class SchoolMasterApprover extendsApprover {public SchoolMasterApprover(String name){super(name); } @Override public void processRequest(PurchaseRequest request) {if(request.getMoney()>30000){System.out.println("该"+request.getMoney()+"的请求已经被"+getName()+"处理啦"); }else{getApprover().processRequest(request); } } }

测试类及结果
package com.cxf.feifei; import org.junit.Test; public class test {@Test public void test(){//创建传递的请求 PurchaseRequest purchaseRequest = new PurchaseRequest(21000.0); //设置处理链 DepartmentApprover departmentApprover = new DepartmentApprover("五千"); CollegeApprover collegeApprover = new CollegeApprover("2w"); ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("3w"); SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("3w+"); departmentApprover.setApprover(collegeApprover); collegeApprover.setApprover(viceSchoolMasterApprover); viceSchoolMasterApprover.setApprover(schoolMasterApprover); //形成环状,不论从哪里开始调用都能准确命中 schoolMasterApprover.setApprover(departmentApprover); //执行责任链 schoolMasterApprover.processRequest(purchaseRequest); } }

设计模式|设计模式-职责链模式
文章图片

springmvc在去匹配handlermapping会返回找到对应的handlermapping并得到handlerexecutionchain(处理程序执行链,由处理程序对象和任何处理程序拦截器组成),使用handlerexecutionchain的handler遍历handleradapter集合找到支持此handler的handleradapter
  • handlerexecutionchain主要负责的是请求拦截器的执行和请求处理,但是本身不处理请求,只是将请求分配给链上注册处理器执行,这是职责链实现方式,减少职责链本身与处理逻辑之间的耦合,规范了处理流程
  • handlerexecutionchain维护了handlerinterceptor的集合,可以向其中注册相应的拦截器

    推荐阅读