|
|
主要内容 |
1、简述
2、实现代码(Talk is cheap,Show me the code)
3、注意点
1、简述
Chain责任链模式在《设计模式之禅》定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条线,并沿着这条链传递该请求,直至有对象处理它为止。
责任链的核心在“链”,由“链”上所有的成员去处理请求并返回结果。 类图中各个角色定义如下:
- Client:客户端向发起请求,责任链对客户端透明
- Handler:责任链抽象类,负责定义处理逻辑以及组装责任链机制
- ConcreteHandler:责任链中的链由多个ConcreteHandler组装而成
结合上述给伪码:
==> Handler类
1 public abstract class Handler {
2 private Handler nextHandler ;
3
4 public final Response handlerMessage(Request request){
5 Response response = null ;
6 // 符合自己处理
7 if(this.getHandlerLevel().equals(request.getRequestLevel())){
8 response = this.echo(request) ;
9 }
10 // 交由其他人处理
11 else if (nextHandler != null) {
12 response = nextHandler.handlerMessage(request) ;
13 }
14 return response ;
15 }
16
17 // 组装责任链
18 public void setNextHandler(Handler nextHandler) {
19 this.nextHandler = nextHandler;
20 }
21
22 // 模版方法 由具体的责任链实现者定义
23 protected abstract Level getHandlerLevel();
24 protected abstract Response echo(Request request);
25 }
==> ConcreteHandler1、ConcreteHandler2、ConcreteHandler3三个类代码类似,都是实际责任链一员且通过继承Handler只需要实现自己的逻辑部分。
1 public class ConcreteHandler1 extends Handler {
2 @Override
3 protected Level getHandlerLevel() {
4 return null;
5 }
6
7 @Override
8 protected Response echo(Request request) {
9 return null;
10 }
11 }
==> Client客户端发起请求 此时包含了责任链的组装和调用 实际可以增加代理简化Client操作
1 public class Client {
2 public static void main(String[] args) {
3
4 // 组装责任链
5 ConcreteHandler1 handler1 = new ConcreteHandler1() ;
6 ConcreteHandler2 handler2 = new ConcreteHandler2() ;
7 ConcreteHandler3 handler3 = new ConcreteHandler3() ;
8 handler1.setNextHandler(handler2);
9 handler2.setNextHandler(handler3);
10
11 // 发起调用
12 Response response = handler1.handlerMessage(new Request()) ;
13 }
以上伪码显示责任链模式基本代码实现,然后实际会依据情况有很多变化。如每个链条只处理部分数据并交由后链条执行,直至责任链的终止,甚至可以没有任何返回结果,接下来小节将展示一个自动组装的责任链demo。
根据责任链模式设计细想,在服务提供的前置增加一个责任链,以完成参数校验、签名、日志、监控、追踪等通用的任务。对于客户端完全透明,对于服务端利用JAVA SPI机制(DUBBO SPI思想)灵活组装配置责任链,而如果结合上强大的spring Bean容器,很容易完成服务框架的定制工作。
下面demo示例:
- Chain: 基本责任链中的链条定义
- ChainHandler:负责责任链的组装和调用逻辑
- ChainLoader:利用JAVA SPI机制,加载具体责任链实现
1 public interface Process<T> {
2 T doProcess() ;
3 }
Process.java
1 package com.nancy.chain.auto;
2
3
4 public interface Chain {
5 int HIGHEST_ORDER = Integer.MIN_VALUE ;
6 int LOWEREST_ORDER = Integer.MAX_VALUE ;
7
8 /**
9 * 处理逻辑
10 * @param chainHandler 责任链组装
11 * @param pos 下一个触发下标
12 * @param process 实际处理逻辑
13 * @return T 返回结果
14 */
15 <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) ;
16
17 /**
18 * 配置等级 越高优先级(越小) 越优先触发
19 * @param
20 * @return
21 */
22 default Integer getOrder() {
23 return HIGHEST_ORDER ;
24 }
25
26 }
Chain.java
1 public abstract class AbstractChain implements Chain, Cloneable {
2
3 }
AbstractChain.java
1 public class ChainHandler extends AbstractChain {
2
3 private List<Chain> chains ;
4
5 public ChainHandler(List<Chain> chains){
6 this.chains = chains ;
7 chains.sort(Comparator.comparingInt(Chain::getOrder));
8 }
9
10 private boolean hasNext(int pos){
11 return chains.size()-1 >= pos ;
12 }
13
14 public List<Chain> getChains() {
15 return chains;
16 }
17
18 public void setChains(List<Chain> chains) {
19 this.chains = chains;
20 }
21
22 @Override
23 public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
24 if(hasNext(pos)) return chainHandler.getChains().get(pos).doChain(chainHandler, ++pos, process);
25 return process.doProcess();
26 }
27 }
ChainHandler.java
1 public class ChainLoader {
2
3 public static List<Chain> loadChain(){
4 List<Chain> chains = new ArrayList<>() ;
5 ServiceLoader<Chain> serviceLoader = ServiceLoader.load(Chain.class);
6 serviceLoader.forEach(chains::add);
7 return chains ;
8 }
9 }
ChainLoader.java
1 package com.nancy.chain.auto.impl;
2
3 import com.nancy.chain.auto.AbstractChain;
4 import com.nancy.chain.auto.Chain;
5 import com.nancy.chain.auto.ChainHandler;
6 import com.nancy.chain.auto.Process;
7 import java.util.List;
8
9 public class HelloChain extends AbstractChain {
10
11 @Override
12 public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
13 System.out.println("HelloChain被触发了");
14 return chainHandler.doChain(chainHandler, pos, process);
15 }
16
17 @Override
18 public Integer getOrder() {
19 return LOWEREST_ORDER-1 ;
20 }
21
22 }
23
24 package com.nancy.chain.auto.impl;
25 import com.nancy.chain.auto.AbstractChain;
26 import com.nancy.chain.auto.ChainHandler;
27 import com.nancy.chain.auto.Process;
28
29 public class LogChain extends AbstractChain {
30
31 @Override
32 public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
33 System.out.println("LogChain被触发了");
34 return chainHandler.doChain(chainHandler, pos, process);
35 }
36
37 @Override
38 public Integer getOrder() {
39 return LOWEREST_ORDER ;
40 }
41
42 }
链条
JAVA SPI机制中的文件: META-INF/services/
com.nancy.chain.auto.impl.HelloChain
com.nancy.chain.auto.impl.LogChain
触发责任链:
package com.nancy.chain.auto;
import com.nancy.chain.auto.spi.ChainLoader;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 加载实现类
List<Chain> chains = ChainLoader.loadChain() ;
// 触发
ChainHandler handler = new ChainHandler(chains) ;
Object res = handler.doChain(handler, 0, (Process<Object>) () -> 100) ;
// 结果
System.out.println("结果" + res);
}
}
结果:
HelloChain被触发了
LogChain被触发了
结果100
3、注意点
- 责任链模式会依据情况有很多变化。可以只由某个“链条”处理请求,或者每个链条只处理部分数据并交由后链条执行,直至责任链的终止。可以有结果返回或者没有任何返回结果。
- 责任链模式可以解耦客户端和服务端,方便进行逻辑叠加。与观察者模式最大不同在于前者观察者是相互对等,之间没有影响。而后者由链条串联成线,链条之间可以建立起逻辑关系,完成某个功能。
- 责任链模式当“链条”很长的时候会存在很大性能问题,设计之初应该考虑长度问题,长度限制在一定范围内。 而责任链之间大多具有逻辑关系,不适用类似观察者模式用异步线程处理的方式。
触发责任链:
[Chùfā zérèn liàn:]
Trigger chain of responsibility:
Prototype原型模式
[Prototype yuánxíng móshì]
Prototype prototype model