责任链模式(Chain of Responsibility) 客户端对象发起请求,请求由下一个对象往下传递,直到被处某一个对象处理了此请求。客户端对象不需要知道是哪个节点进行了处理。这就可以在不景响客户端对象的情况下动态地重新组织和分配责任。
白话:一条对象链调下去。 A->B->C->D A 持有 B 的引用,B 持有 C 的引用,C 持有 D 的引用。 开始执行A的逻辑,A能处理就处理了,不能处理就拿着B的引用,调用B去处理。整个逻辑就是这样一直往下去推。
1.角色 抽象处理者(Hand): 处理请求的接口。所有处理者都实现这个接口。 接口可以定义出一个方法以设定和返回对下家的引用。通常由抽象类或接口实现。 具体处理者(ConcreteHandler) 具体处理者接到请求后可以选择将请求处理掉,或者将请求传给下家。 因为具体处理都持有下家的引用。
2.处理顺序 可线性,可循环。
1.手动构建责任链 这种方式,我觉得挺low的,需要手动构建,不过在刚学习的时候,还是可以帮助理解。 需要角色:
Handler
Handler实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 abstract class Handler { private Handler nextHandler; public void setNextHandler (Handler nextHandler) { this .nextHandler = nextHandler; } public void handleRequest (String request) { if (canHandle(request)) { processRequest(request); } else if (nextHandler != null ) { nextHandler.handleRequest(request); } else { System.out.println("No handler available for the request: " + request); } } protected abstract boolean canHandle (String request) ; protected abstract void processRequest (String request) ; } class ConcreteHandlerA extends Handler { protected boolean canHandle (String request) { return request.equals("A" ); } protected void processRequest (String request) { System.out.println("ConcreteHandlerA is handling the request: " + request); } } class ConcreteHandlerB extends Handler { protected boolean canHandle (String request) { return request.equals("B" ); } protected void processRequest (String request) { System.out.println("ConcreteHandlerB is handling the request: " + request); } } class ConcreteHandlerC extends Handler { protected boolean canHandle (String request) { return request.equals("C" ); } protected void processRequest (String request) { System.out.println("ConcreteHandlerC is handling the request: " + request); } } public class Test { public static void main (String[] args) { Handler handlerA = new ConcreteHandlerA(); Handler handlerB = new ConcreteHandlerB(); Handler handlerC = new ConcreteHandlerC(); handlerA.setNextHandler(handlerB); handlerB.setNextHandler(handlerC); handlerA.handleRequest("A" ); handlerA.handleRequest("B" ); handlerA.handleRequest("C" ); handlerA.handleRequest("D" ); } }
2.遍历方式访问责任链 这种方式的优点就是可以动态的添加责任链类,将需要的继承接口即可成为责任链的一环。 新增或移动都不需要额外的改代码,耦合性很低。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 遍历方式模式 interface Handler { boolean canHandle (String request) ; void processRequest (String request) ; } import java.util.LinkedList;import java.util.List;class HandlerImpl implements Handler { private final List<Handler> handlers; public HandlerImpl () { handlers = new LinkedList<>(); } public void addHandler (Handler handler) { handlers.add(handler); } public void handleRequest (String request) { for (Handler handler : handlers) { if (handler.canHandle(request)) { handler.processRequest(request); return ; } } System.out.println("No handler available for the request: " + request); } public boolean canHandle (String request) { return false ; } public void processRequest (String request) { } } class ConcreteHandlerA implements Handler { public boolean canHandle (String request) { return request.equals("A" ); } public void processRequest (String request) { System.out.println("ConcreteHandlerA is handling the request: " + request); } } class ConcreteHandlerB implements Handler { public boolean canHandle (String request) { return request.equals("B" ); } public void processRequest (String request) { System.out.println("ConcreteHandlerB is handling the request: " + request); } } class ConcreteHandlerC implements Handler { public boolean canHandle (String request) { return request.equals("C" ); } public void processRequest (String request) { System.out.println("ConcreteHandlerC is handling the request: " + request); } } public class Test { public static void main (String[] args) { HandlerImpl handlerChain = new HandlerImpl(); handlerChain.addHandler(new ConcreteHandlerA()); handlerChain.addHandler(new ConcreteHandlerB()); handlerChain.addHandler(new ConcreteHandlerC()); handlerChain.handleRequest("A" ); handlerChain.handleRequest("B" ); handlerChain.handleRequest("C" ); handlerChain.handleRequest("D" ); } }
3.基于顺序的责任链 这里需要注意的是 getPriority
方法,这个用来指定优先及。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 interface Handler { boolean canHandle (String request) ; void processRequest (String request) ; int getPriority () ; } class ConcreteHandlerA implements Handler { public boolean canHandle (String request) { return request.equals("A" ); } public void processRequest (String request) { System.out.println("ConcreteHandlerA is handling the request: " + request); } public int getPriority () { return 1 ; } } class ConcreteHandlerB implements Handler { public boolean canHandle (String request) { return request.equals("B" ); } public void processRequest (String request) { System.out.println("ConcreteHandlerB is handling the request: " + request); } public int getPriority () { return 2 ; } } class ConcreteHandlerC implements Handler { public boolean canHandle (String request) { return request.equals("C" ); } public void processRequest (String request) { System.out.println("ConcreteHandlerC is handling the request: " + request); } public int getPriority () { return 3 ; } }
构建顺序 下面的代码中,只有一段代码需要注意,放到最后解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import java.util.PriorityQueue;import java.util.Queue;class HandlerImpl implements Handler { private final Queue<Handler> handlers; public HandlerImpl () { handlers = new PriorityQueue<>((h1, h2) -> h2.getPriority() - h1.getPriority()); } public void addHandler (Handler handler) { handlers.add(handler); } public void handleRequest (String request) { for (Handler handler : handlers) { if (handler.canHandle(request)) { handler.processRequest(request); return ; } } System.out.println("No handler available for the request: " + request); } public boolean canHandle (String request) { return false ; } public void processRequest (String request) { } public int getPriority () { return 0 ; } }
(h1, h2) -> h2.getPriority() - h1.getPriority()
是一个lambda表达式,它定义了一个比较器。比较器用于确定元素在队列中的顺序。 在这个比较器中,h1 和 h2 是两个要进行比较的元素。getPriority() 是处理器接口中定义的方法,用于获取处理器的优先级。 比较器的逻辑是将两个元素的优先级进行比较,如果 h2 的优先级大于 h1 的优先级,返回一个正数;如果 h2 的优先级小于 h1 的优先级,返回一个负数;如果两个元素的优先级相同,返回0。 根据这个比较器的逻辑,优先队列会根据处理器的优先级进行排序,优先级较高的处理器将排在队列的前面。 这样,在调用 handlers.add(handler) 将处理器添加到优先队列时,队列会根据处理器的优先级自动进行排序。
总结 实际应用的中比如filter就是一种典型的责任链,而在实际业务开发中,责任链非常常用,将业务逻辑组织成一个责任链条,传递每一环业务的结果。很有帮助,实际中使用Spring来组装的场景比较多。非Spring的话,也基本就是第三种方式就够用了。