1.责任链模式 概述:
责任链模式(职责链模式),为了避免请求发送者与多个请求处理者耦合在一起,将所有的请求的处理者通过前一个对象记住下一个对象的引用,从而形成一条链式结构。当请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
2.职责链模式 结构:
- 抽象处理者角色(
Handler
):定义一个处理请求的接口,包含抽象处理方法和一个后继连接。 - 具体处理者角色(
Concrete Handler
):实现抽象处理者的处理请求方法,判断能否处理本次请求,如果可以处理请求则进行处理,否则将请求转发给他的后继者。 - 客户类角色(
Client
):创建处理链,并向链头的具体处理者对象提交处理请求,不关心处理细节和请求的传递过程。
3.责任链模式 示例:
现在要开发一个请求流程系统。请假在一天以内只需要小组长同意即可;请假一到三天需要部门经理同意;请假三天以上需要总经理同意。
首先,需要定义一个请求类:
@Data @NoArgsConstructor @AllArgsConstructor public class Request { // 请求主题: private String topic; // 请求级别: private int level; // 请求内容: private String content; }
创建一个抽象的Handler
,抽象请求处理者角色:
/** * 抽象请求处理者角色 */ public abstract class Handler { // 请求级别:请求级别一一下由HandlerOne处理;请求一级别到三级别有HandlerTwo处理;请求级别三到七由HandlerThree处理 protected final static int LEVEL_ONE = 1; protected final static int LEVEL_THREE = 3; protected final static int LEVEL_SEVEN = 7; // 该领导处理请假的区间: private int levelStart; private int levelEnd; // 声明后继者角色(上级领导) private Handler nextHandler; public Handler(int levelStart) { this.levelStart = levelStart; } public Handler(int levelStart, int levelEnd) { this.levelStart = levelStart; this.levelEnd = levelEnd; } public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; } /** * 各级Handler处理请求的顺序链 * @param request 请求 */ protected abstract void handler(Request request); /** * 提交处理请求 * @param request 请求 */ public final void submit(Request request) { // 判断请求是否能被当前Handler处理: if (request.getLevel() > this.levelStart && request.getLevel() <= this.levelEnd){ // Handler进行处理: this.handler(request); System.out.println("处理完成!"); } // 当前Handler无法处理本次提交的请求,交给后继处理者进行处理。 if (this.nextHandler != null && request.getLevel() > this.levelEnd) { // 提交给后继Handler进行处理: this.nextHandler.submit(request); } } }
在抽象请求处理者角色中定义处理者的处理规则(调用逻辑链)。然后实现各级别具体处理者角色:
public class HandlerOne extends Handler { public HandlerOne() { super(0, Handler.LEVEL_ONE); } @Override protected void handler(Request request) { System.out.println(request.getTopic() + "请求:" + request.getLevel()); System.out.println("HandlerOne,开始处理请求!"); } }
public class HandlerTwo extends Handler { public HandlerTwo() { super(Handler.LEVEL_ONE, Handler.LEVEL_THREE); } @Override protected void handler(Request request) { System.out.println(request.getTopic() + "请求:" + request.getLevel()); System.out.println("HandlerTwo,开始处理请求!"); } }
public class HandlerThree extends Handler { public HandlerThree() { super(Handler.LEVEL_THREE, Handler.LEVEL_SEVEN); } @Override protected void handler(Request request) { System.out.println(request.getTopic() + "请求:" + request.getLevel()); System.out.println("HandlerThree,开始处理请求!"); } }
使用Client
角色将职责链进行串联:
public class Client { public static void main(String[] args) { // 1.创建一个请求对象: Request request = new Request("Krian", 8,"请求撤退!"); // 2.创建各级领导对象: HandlerOne handlerOne = new HandlerOne(); HandlerTwo handlerTwo = new HandlerTwo(); HandlerThree handlerThree = new HandlerThree(); // 3.设置处理链: handlerOne.setNextHandler(handlerTwo); handlerTwo.setNextHandler(handlerThree); // 4.提交处理请求: handlerOne.submit(request); } }
4.责任链模式 优缺点:
责任链模式的优点:
- 降低了对象之间的耦合度。该模式降低了请求发送者和接受者之间的耦合,请求者无需向每一个请求的处理者都进行关联。
- 增强了系统的可扩展性。可以根据需要增加新的请求处理者,满足开闭原则。
- 增强了给对象指派职责的灵活性。当工作流程发生了变化,可以动态地改变链内的成员或者修改他们的次序,也可以动态地新增或者删除责任。
- 责任链简化了对象之间的连接。一个对象只需要保持一个指向其后继者的引用,不需要保持对其他处理者的引用,避免了众多的
if-else
结构的出现。 - 责任分担。每个类只需要处理自己该处理的工作,不能处理的就传递给下一个对象完成,明确各个类的责任范围,符合类的单一职责原则。
责任链模式的缺点:
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到责任链的末端都得不到处理
- 对于比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于责任链的错误设置而导致系统出现错误,可能造成循环调用。