行为模式-责任链模式
定义:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关 系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。)
责任链模式通用类图
责任链设计模式的核心思想是解耦请求的发送者和接收者,并让多个处理者都有机会处理请求。通过将处理者组织成一条链,请求会在链上依次传递,每个处理者都可以决定是否处理该请求以及是否将请求继续传递给下一个处理者。这种设计方式使得系统可以在不修改现有代码的情况下,动态地调整处理者的顺序或增加新的处理者,提高了系统的灵活性和可扩展性。
角色:
责任链模式包含以下几个核心角色:
1、抽象处理者(Handler)
抽象处理者定义了处理请求的接口,通常包含一个处理请求的方法和一个设置下一个处理者的方法。抽象处理者可以是抽象类或接口,它规定了所有具体处理者必须实现的方法。
2、具体处理者(Concrete Handler)
具体处理者是抽象处理者的实现类,它负责处理请求。每个具体处理者都会判断自己是否有能力处理该请求,如果可以则进行处理,否则将请求传递给下一个处理者。具体处理者中通常包含对下一个处理者的引用。
3、客户端(Client)
客户端负责创建处理者链,并将请求发送给链上的第一个处理者。客户端不需要知道请求具体是由哪个处理者处理的,只需要将请求发送到链上即可。
代码示例:
责任链设计模式有多种实现方式,下面通过一个请假审批的示例来展示其典型实现。
// 抽象处理者:审批者
public abstract class Approver {protected Approver nextApprover;public void setNextApprover(Approver nextApprover) {this.nextApprover = nextApprover;}// 处理请假请求的抽象方法public abstract void processRequest(LeaveRequest request);}
// 具体处理者:组长
public class TeamLeader extends Approver {@Overridepublic void processRequest(LeaveRequest request) {if (request.getDays() <= 1) {System.out.println("组长批准了" + request.getName() + "的" + request.getDays() + "天请假申请");} else if (nextApprover != null) {System.out.println("组长无法处理" + request.getName() + "的" + request.getDays() + "天请假申请,已转交上级");nextApprover.processRequest(request);}}}
// 具体处理者:经理
public class Manager extends Approver {@Overridepublic void processRequest(LeaveRequest request) {if (request.getDays() <= 3) {System.out.println("经理批准了" + request.getName() + "的" + request.getDays() + "天请假申请");} else if (nextApprover != null) {System.out.println("经理无法处理" + request.getName() + "的" + request.getDays() + "天请假申请,已转交上级");nextApprover.processRequest(request);}}}
// 具体处理者:总监
public class Director extends Approver {@Overridepublic void processRequest(LeaveRequest request) {if (request.getDays() <= 7) {System.out.println("总监批准了" + request.getName() + "的" + request.getDays() + "天请假申请");} else {System.out.println("总监拒绝了" + request.getName() + "的" + request.getDays() + "天请假申请,请假天数过长");}}}
// 请假请求类
public class LeaveRequest {private String name;private int days;public LeaveRequest(String name, int days) {this.name = name;this.days = days;}public String getName() {return name;}public int getDays() {return days;}}
// 客户端代码
public class ChainOfResponsibilityClient {public static void main(String[] args) {// 创建处理者Approver teamLeader = new TeamLeader();Approver manager = new Manager();Approver director = new Director();// 构建责任链teamLeader.setNextApprover(manager);manager.setNextApprover(director);// 提交请假申请LeaveRequest request1 = new LeaveRequest("张三", 1);teamLeader.processRequest(request1);System.out.println("-------------------");LeaveRequest request2 = new LeaveRequest("李四", 3);teamLeader.processRequest(request2);System.out.println("-------------------");LeaveRequest request3 = new LeaveRequest("王五", 5);teamLeader.processRequest(request3);System.out.println("-------------------");LeaveRequest request4 = new LeaveRequest("赵六", 10);teamLeader.processRequest(request4);}}
优点 :
1、解耦请求发送者和接收者:责任链模式将请求的发送者和接收者解耦,发送者不需要知道请求具体由哪个处理者处理,只需要将请求发送到链上即可。这提高了系统的灵活性和可维护性。
2、简化对象间的关系:责任链模式使得处理者之间的关系变得简单,每个处理者只需要知道自己的下一个处理者,不需要了解整个链的结构。这降低了系统的复杂度。
3、动态调整链结构:在运行时,可以动态地调整责任链的结构,如增加、删除或修改处理者,不需要修改客户端代码。这提高了系统的可扩展性。
4、符合开闭原则:责任链模式可以在不修改现有代码的情况下,通过增加新的处理者来扩展系统的功能,符合开闭原则。
缺点:
1、请求可能不被处理:由于请求在链上传递,直到有一个处理者处理它为止,如果链没有正确配置,可能会导致请求最终没有被任何处理者处理。
2、调试困难:责任链模式可能会导致代码的调试变得困难,特别是当链比较长或处理者之间的关系复杂时,很难跟踪请求的传递过程。
3、性能问题:如果责任链过长,请求的处理可能会涉及多个处理者,导致性能下降。在这种情况下,需要考虑优化链的结构或采用其他设计模式。
使用场景:
(一)多级审批流程
在企业管理系统中,经常会遇到需要多级审批的流程,如请假审批、报销审批等。责任链设计模式可以将各个审批环节连接成一条链,使请求在链上依次传递,直到被某个审批者处理。
(二)请求过滤
在 Web 应用中,请求通常需要经过多个过滤器的处理,如身份验证、权限检查、日志记录等。责任链设计模式可以将这些过滤器组织成一条链,每个过滤器负责处理特定的任务,并决定是否将请求继续传递给下一个过滤器。
(三)事件处理
在图形界面应用中,事件处理通常采用责任链模式。当用户触发一个事件时,事件会在组件层次结构中依次传递,直到被某个组件处理。
(四)游戏中的技能连招
在游戏开发中,技能连招系统可以使用责任链模式实现。每个技能节点可以处理特定的技能效果,并决定是否将连招传递给下一个技能节点。
责任链设计模式通过将请求的发送者和接收者解耦,并让多个处理者都有机会处理请求,为我们提供了一种优雅的请求处理方式。它在多级审批、请求过滤、事件处理等场景中有着广泛的应用。在实际开发中,我们可以根据具体的需求来设计责任链的结构,确保请求能够在链上被正确处理。同时,我们也要注意责任链模式可能带来的问题,如请求不被处理、调试困难和性能问题等,合理使用该模式,以达到最佳的设计效果。