思明自助建站软件,设计网络,优化网站,无锡做网站公司文章目录 责任链模式的定义场景示例责任链模式实现方案责任链模式扩展责任链模式的优缺点责任链模式在框架源码中的应用 责任链模式的定义
责任链模式又称职责链模式#xff0c;是一种行为型设计模式。官方描述#xff1a;使多个对象都有机会处理请求#xff0c;从而避免请… 文章目录 责任链模式的定义场景示例责任链模式实现方案责任链模式扩展责任链模式的优缺点责任链模式在框架源码中的应用 责任链模式的定义
责任链模式又称职责链模式是一种行为型设计模式。官方描述使多个对象都有机会处理请求从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链并沿着这条链传递该请求直到有一个对象处理它为止。
原文链接或文中示例代码下载请关注公众号【Qin的学习营地】回复【责任链模式】
场景示例
上述定义是对责任链模式这种思想的归纳总结理解起来稍微抽象下面结合一种场景逐步深入责任链模式。
企业采购
在企业中经常需要采购一些物品小到一些廉价的生活用品大到昂贵的精密器械采购金额高低各异不同采购金额需要由不同领导层次的管理人审批。比如金额在1万以下的只需部门负责人审批即可金额超过1万且10万以下部门负责人无权审批需交由总经理审批金额超过10万以上则只能层层上报到董事长由董事长审批了如下图。
简单的 if…else 实现方案
在上述企业采购中采购金额不同分别交由不同层次的领导审批这里最简单的实现方案就是使用 if…else 判断。代码如下
// 采购审批处理类
public class PurchaseHandler {// 采购审批处理方法public String handleRequest(String purchaserName, Double purchaseAmount){if (purchaseAmount 10000.0){ // 部门负责人审批return approvalByDepartmentLeader(purchaserName, purchaseAmount);} else if (purchaseAmount 100000.0) { // 总经理审批return approvalByManager(purchaserName, purchaseAmount);} else { // 董事长审批return approvalByChairman(purchaserName, purchaseAmount);}}private String approvalByDepartmentLeader(String purchaserName, Double purchaseAmount){return (purchaserName 申请采购金额 purchaseAmount 元, 审批人部门负责人);}private String approvalByManager(String purchaserName, Double purchaseAmount){return (purchaserName 申请采购金额 purchaseAmount 元, 审批人总经理);}private String approvalByChairman(String purchaserName, Double purchaseAmount){return (purchaserName 申请采购金额 purchaseAmount 元, 审批人董事长);}
}if…else 实现方案存在的问题
分析 if…else 实现方案存在的问题
代码结构不够清晰干净。采购审批中的每个审批环节可能存在业务逻辑改动比如部门负责人审核完之后还是总经理签字这就需要修改审批处理类和方法。采购审批流程发生变化当金额超过一定数额时也不能完全由董事长审批需要通过董事会投票决定这就需要增加一个审批步骤同样也需要修改源代码。
责任链模式实现方案
仔细分析上面的场景客户端提出一个采购申请请求对于客户端来说他不需要关心是谁审批后续审批流上可能是由部门负责人、总经理、董事长任一符合方进行审批。这样从部门负责人到总经理、再到董事长审批流程可以看作是一条链客户端提出的申请请求在这个链上传递直到对应的责任人审批为止。
流程中可能在任意位置新增环节每个环节可能会修改自己的处理逻辑为了方便修改或复用每个环节或者扩展新增环节组合不同流程可以将每个环节作为一个单独的对象并且只实现单一的处理功能这样细粒度划分功能有利于降低修改的影响面和提高扩展性。
责任链模式概念
责任链模式就体现了上述细粒度抽取的思想核心在于引入了一个抽象处理者。
责任链模式结构图
责任链模式中的角色 Handler抽象处理者一个处理请求的接口一般设计为抽象类其中定义一个处理请求的抽象方法不同的具体处理者实现该方法每个处理者可能需要将请求传递给下一个处理者所以还可以定义一个处理者对象作为后继者的引用从而实现一条链。 ConcreteHandler具体处理者抽象处理者的具体实现子类实现抽象处理类中的抽象方法方法需要实现的两个功能一是处理请求处理具体处理者职责范围内的请求二是转发请求不在该具体处理者职责范围内的请求就将请求转发给后继者处理。 Client客户端责任链客户端组合处理者对象构造责任链同时请求责任链处理请求对象。 组合的顺序很重要如果顺序不对处理的结果可能就不是符合要求的。 Client 不算责任链中的角色外部使用责任链模式时自行创建。
责任链模式代码示例
1、定义抽象处理者接口类类中持有下一个处理者对象同时实现请求处理方法
// 定义责任链抽象接口类
public abstract class Handler {// 持有下一个处理者对象引用protected Handler nextHandler;// 设置下一个处理者对象public void setNextHandler(Handler nextHandler) {this.nextHandler nextHandler;}// 处理采购申请请求public abstract String handleRequest(String purchaserName, Double purchaseAmount);
}2、实现具体处理者类实现处理请求的具体方法方法内部逻辑处理请求的具体逻辑或者将请求对象传递给下一个处理者。这里实现三个具体处理者。 DepartmentLeaderHandler 部门负责人处理类 // 部门负责人处理类
public class DepartmentLeaderHandler extends Handler {Overridepublic String handleRequest(String purchaserName, Double purchaseAmount) {// 职责范围内处理审批请求if (purchaseAmount 10000){return (purchaserName 申请采购金额 purchaseAmount 元, 审批人部门负责人);} else {// 职责范围外处理交由下一个处理者处理if (this.nextHandler ! null){return this.nextHandler.handleRequest(purchaserName, purchaseAmount);}}return null;}
}ManagerHandler 总经理处理类 // 总经理处理类
public class ManagerHandler extends Handler {Overridepublic String handleRequest(String purchaserName, Double purchaseAmount) {// 职责范围内处理审批请求if (purchaseAmount 100000){return (purchaserName 申请采购金额 purchaseAmount 元, 审批人总经理);} else {// 职责范围外处理交由下一个处理者处理if (this.nextHandler ! null){return this.nextHandler.handleRequest(purchaserName, purchaseAmount);}}return null;}
}ChairmanHandler 董事长处理类 // 董事长处理类
public class ChairmanHandler extends Handler {Overridepublic String handleRequest(String purchaserName, Double purchaseAmount) {// 职责范围内处理审批请求if (purchaseAmount 100000){return (purchaserName 申请采购金额 purchaseAmount 元, 审批人董事长);} else {// 职责范围外处理交由下一个处理者处理if (this.nextHandler ! null){return this.nextHandler.handleRequest(purchaserName, purchaseAmount);}}return null;}
}3、客户端组合处理者构建责任链并调用
public class Client {public static void main(String[] args) {// 创建责任链上的每个处理者对象DepartmentLeaderHandler departmentLeaderHandler new DepartmentLeaderHandler();ManagerHandler managerHandler new ManagerHandler();ChairmanHandler chairmanHandler new ChairmanHandler();// 组合处理者对象构造责任链departmentLeaderHandler.setNextHandler(managerHandler);managerHandler.setNextHandler(chairmanHandler);// 提交请求调用责任链调用责任链第一个处理者对象即可String result departmentLeaderHandler.handleRequest(采购人员, 105000.0);System.out.println(result);}
}当调用责任链处理请求时并不知道谁会真正处理请求只知道将请求提交到第一个处理者对象。从第一个处理者对象开始整个责任链中的对象要么自己处理请求要么继续转发给下一个接收者。
从 if…else 判断到责任链模式的使用可以看出代码结构变得清晰了。 责任链模式很好的满足了单一职责和开闭原则。
在责任链模式中可能没有合适的处理者请求不一定会被处理所以可以在最后加上不支持处理该请求的提示。
责任链模式扩展
责任链构建方式
责任链构建方式多种多样现在总结三种基本的实现方式
1、客户端在提交请求前组合处理者构造责任链即在使用的时候动态组合链。如前面责任链的实现就是这种。
2、可以在抽象处理者 Handler 内部实现责任链的组合。
3、由各个具体处理者自己决定后继者这种方式要求每个处理者了解业务流程。
纯与不纯的责任链
纯的责任链模式
纯的责任链模式的每个处理者对象只会做两件事要么处理请求并返回要么将请求传递给链上的下一个处理者对象。
不纯的责任链模式
不满足纯的责任链模式要求的就是不纯的责任链也可以称为功能链。一个请求在责任链中传递每个处理者对象负责处理请求的某一方面的功能处理完成后不是停止而是继续向后继者传递请求后继者可以继续处理该请求。在实际应用开发中进行业务处理之前通常需要进行权限检查、通用数据校验、数据逻辑校验等处理然后才开始真正的业务逻辑实现。可以把这些功能分散到一个功能链中。这样做的目的是使程序结构更加灵活而且复用性会更好。比如通用的权限检查只需要做一份然后就可以在多个功能链中使用了。
责任链模式的优缺点
优点 请求者和处理者松散耦合 在责任链模式中请求者并不知道接收者是谁也不知道具体如何处理请求者只是负责向责任链发出请求就可以了。而每个处理者对象也不用管请求者或者是其他的处理者对象只负责处理自己的部分其他的就交给其他的处理者对象去处理。并且链中的对象不需要知道链的结构可以由客户端负责链的创建降低耦合。 动态组合 责任链模式会把功能处理分散到单独的处理者对象中然后在使用的时候可以动态组合处理者形构造责任链从而可以灵活地给对象分配职责也可以灵活地实现和改变对象的职责。 符合开闭原则 在系统中新增具体处理者对象时无需修改原代码只需要在客户端重新构建责任链即可。
缺点 产生很多细粒度对象 责任链模式会把功能处理分散到单独的处理者对象中也就是每个处理者对象只处理一个方面的功能要把整个业务处理完需要很多处理者对象的组合这样会产生大量的细粒度处理者对象。 不一定能被处理 责任链模式的每个处理者对象只负责自己处理的那一部分因此可能会出现某个请求把整个链传递完了都没有处理者对象处理它。这就需要在使用责任链模式的时候需要提供默认的处理并且注意构建的链的有效性。 责任链模式可能会带来一些额外的性能损耗因为它每次执行请求都要从链子开头开始遍历。甚至责任链构建不当出现循环调用导致系统陷入死循环。
责任链模式在框架源码中的应用
完整后续内容请关注公众号【Qin的学习营地】回复【责任链模式】