java设计模式解析(11) Chain责任链模式
设计模式系列文章 |
java设计模式解析(1) Observer观察者模式 |
主要内容 |
2、实现代码(Talk is cheap,Show me the code)
1、简述
Chain责任链模式在《设计模式之禅》定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条线,并沿着这条链传递该请求,直至有对象处理它为止。
责任链的核心在“链”,由“链”上所有的成员去处理请求并返回结果。 类图中各个角色定义如下:
- Client:客户端向发起请求,责任链对客户端透明
- Handler:责任链抽象类,负责定义处理逻辑以及组装责任链机制
- ConcreteHandler:责任链中的链由多个ConcreteHandler组装而成
结合上述给伪码:
==> Handler类
public abstract class Handler {
private Handler nextHandler ; public final Response handlerMessage(Request request){
Response response = null ;
// 符合自己处理
if(this.getHandlerLevel().equals(request.getRequestLevel())){
response = this.echo(request) ;
}
// 交由其他人处理
else if (nextHandler != null) {
response = nextHandler.handlerMessage(request) ;
}
return response ;
} // 组装责任链
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
} // 模版方法 由具体的责任链实现者定义
protected abstract Level getHandlerLevel();
protected abstract Response echo(Request request);
}
==> ConcreteHandler1、ConcreteHandler2、ConcreteHandler3三个类代码类似,都是实际责任链一员且通过继承Handler只需要实现自己的逻辑部分。
public class ConcreteHandler1 extends Handler {
@Override
protected Level getHandlerLevel() {
return null;
} @Override
protected Response echo(Request request) {
return null;
}
}
==> Client客户端发起请求 此时包含了责任链的组装和调用 实际可以增加代理简化Client操作
public class Client {
public static void main(String[] args) { // 组装责任链
ConcreteHandler1 handler1 = new ConcreteHandler1() ;
ConcreteHandler2 handler2 = new ConcreteHandler2() ;
ConcreteHandler3 handler3 = new ConcreteHandler3() ;
handler1.setNextHandler(handler2);
handler2.setNextHandler(handler3); // 发起调用
Response response = handler1.handlerMessage(new Request()) ;
}
以上伪码显示责任链模式基本代码实现,然后实际会依据情况有很多变化。如每个链条只处理部分数据并交由后链条执行,直至责任链的终止,甚至可以没有任何返回结果,接下来小节将展示一个自动组装的责任链demo。
2、实现代码(Talk is cheap,Show me the code)
根据责任链模式设计细想,在服务提供的前置增加一个责任链,以完成参数校验、签名、日志、监控、追踪等通用的任务。对于客户端完全透明,对于服务端利用JAVA SPI机制(DUBBO SPI思想)灵活组装配置责任链,而如果结合上强大的spring Bean容器,很容易完成服务框架的定制工作。
下面demo示例:
- Chain: 基本责任链中的链条定义
- ChainHandler:负责责任链的组装和调用逻辑
- ChainLoader:利用JAVA SPI机制,加载具体责任链实现
public interface Process<T> {
T doProcess() ;
}
Process.java
package com.nancy.chain.auto; public interface Chain {
int HIGHEST_ORDER = Integer.MIN_VALUE ;
int LOWEREST_ORDER = Integer.MAX_VALUE ; /**
* 处理逻辑
* @param chainHandler 责任链组装
* @param pos 下一个触发下标
* @param process 实际处理逻辑
* @return T 返回结果
*/
<T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) ; /**
* 配置等级 越高优先级(越小) 越优先触发
* @param
* @return
*/
default Integer getOrder() {
return HIGHEST_ORDER ;
} }
Chain.java
public abstract class AbstractChain implements Chain, Cloneable { }
AbstractChain.java
public class ChainHandler extends AbstractChain { private List<Chain> chains ; public ChainHandler(List<Chain> chains){
this.chains = chains ;
chains.sort(Comparator.comparingInt(Chain::getOrder));
} private boolean hasNext(int pos){
return chains.size()-1 >= pos ;
} public List<Chain> getChains() {
return chains;
} public void setChains(List<Chain> chains) {
this.chains = chains;
} @Override
public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
if(hasNext(pos)) return chainHandler.getChains().get(pos).doChain(chainHandler, ++pos, process);
return process.doProcess();
}
}
ChainHandler.java
public class ChainLoader { public static List<Chain> loadChain(){
List<Chain> chains = new ArrayList<>() ;
ServiceLoader<Chain> serviceLoader = ServiceLoader.load(Chain.class);
serviceLoader.forEach(chains::add);
return chains ;
}
}
ChainLoader.java
package com.nancy.chain.auto.impl; import com.nancy.chain.auto.AbstractChain;
import com.nancy.chain.auto.Chain;
import com.nancy.chain.auto.ChainHandler;
import com.nancy.chain.auto.Process;
import java.util.List; public class HelloChain extends AbstractChain { @Override
public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
System.out.println("HelloChain被触发了");
return chainHandler.doChain(chainHandler, pos, process);
} @Override
public Integer getOrder() {
return LOWEREST_ORDER-1 ;
} } package com.nancy.chain.auto.impl;
import com.nancy.chain.auto.AbstractChain;
import com.nancy.chain.auto.ChainHandler;
import com.nancy.chain.auto.Process; public class LogChain extends AbstractChain { @Override
public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
System.out.println("LogChain被触发了");
return chainHandler.doChain(chainHandler, pos, process);
} @Override
public Integer getOrder() {
return LOWEREST_ORDER ;
} }
链条
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、注意点
- 责任链模式会依据情况有很多变化。可以只由某个“链条”处理请求,或者每个链条只处理部分数据并交由后链条执行,直至责任链的终止。可以有结果返回或者没有任何返回结果。
- 责任链模式可以解耦客户端和服务端,方便进行逻辑叠加。与观察者模式最大不同在于前者观察者是相互对等,之间没有影响。而后者由链条串联成线,链条之间可以建立起逻辑关系,完成某个功能。
- 责任链模式当“链条”很长的时候会存在很大性能问题,设计之初应该考虑长度问题,长度限制在一定范围内。 而责任链之间大多具有逻辑关系,不适用类似观察者模式用异步线程处理的方式。
java设计模式解析(11) Chain责任链模式的更多相关文章
- Java设计模式(14)责任链模式(Chain of Responsibility模式)
Chain of Responsibility定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合, ...
- Java设计模式(九)责任链模式 命令模式
(十七)责任链模式 责任链模式的目的是通过给予多个对象处理请求的机会,已解除请求发送者与接受者之间的耦合关系.面对对象的开发力求对象之前保持松散耦合,确保对象各自的责任最小化.这种设计能够使得系统更加 ...
- java设计模式(五)责任链模式
很多对象有每个对象对其下家的引用而连接起来形成一条链,请求在这条链上传递,直到链上某个对象决定处理此请求,应用场景如单位审批流程等. 要点:1)抽象处理者角色:定义处理请求接口及设定下家引用 2 ...
- php设计模式课程---5、责任链模式是什么
php设计模式课程---5.责任链模式是什么 一.总结 一句话总结: 自己权限不够,就交给上级处理 1.选择结构怎么做到面向对象开闭原则? 也就是说if,都可以用接口的实现来实现,这样就避免了更新的时 ...
- 【设计模式 - 13】之责任链模式(Chain Of Responsibility)
1 模式简介 责任链模式的简介: 1. 责任链模式为请求创建了一个接收者对象的链,每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一 ...
- 浅谈Java五大设计原则之责任链模式
首先我们得先定义一个责任链模式: 责任链模式是一种线性执行流程,多个对象都有机会去执行同一个任务,只是在执行过程中, 由于执行的权利和范围不一样,那么当自己不能处理此任务时,就必须将这个任务抛给下一个 ...
- 设计模式-(15)责任链模式 (swift版)
一,概念: 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行 ...
- 设计模式Design Pattern(3) -- 责任链模式
什么是责任链模式? 责任链模式(Chain of Responsibility Pattern):请求知道公开接口,但不知道那个具体类处理,这些具体处理类对象连接成一条链.请求沿着这条链传递,直到有对 ...
- java23种设计模式之十:责任链模式
最近在学习netty中发现其中用到了责任链模式,然后结合自己在写代码中遇到了大量写if...else的情况,决定学习一下责任链模式. 一.什么样的场景下会选择用责任链模式 我们在进行业务逻辑判断时,需 ...
随机推荐
- 倒数第K个结点
typedef struct Lnode{ int data; struct Lnode *next; }Lnode,*Link; Link fi(Link head,int k){ Link fa ...
- 【剑指offer】面试题 18. 删除链表的节点
面试题 18. 删除链表的节点
- son-server模拟http mock数据
json-server 前端开发中,想通过异步请求服务端json数据,但是服务端还没有开发完,此时可以快速启动一个server服务 1,安装json-server插件 npm -g add json- ...
- Apache Kafka用例
1.目标 在我们上一篇Kafka教程中,我们讨论了Kafka Pros and Cons.今天,在这篇Kafka文章中,我们将讨论Apache Kafka用例和Kafka应用程序.Kafka是新数据堆 ...
- STM32F030-UART1_DMA使用提示
STM32F030-UART1_DMA使用提示 前言: 今天把STM32F030C8T6的串口DMA学习了一下,为了加快各位研发人员的开发进度,避免浪费大量的时间在硬件平台上,写出个人代码调试的经验. ...
- 编写第一个Linux环境下程序的编译,下载记录
跟着韦东山学习Linux: 今天系统系统性的学了代码的编译下载,条记录一下: 一,代码:001_led_on.S,就把下面代码编译后Bin文件下载进2440处理器. /* * 点亮LED1: gpf4 ...
- 用pyinstaller打包一个exe程序
打包单个exe文件 -F 选项可以打出一个exe文件,默认是 -D,意思是打成一个文件夹. pyinstaller -F TestDataGen.py 打出的桌面程序去掉命令行黑框 -w 选项可以打桌 ...
- [CF868E]Policeman and a Tree
题目大意:有一棵$n$个点的带边权的树,上面有$m$个罪犯,速度为任意大,有一个警察在点$S$,速度为$1$.若警察和罪犯在同一个地方,罪犯就被干掉了,警察希望干掉所有罪犯时间最短,而罪犯希望最大化这 ...
- python多线程一些知识点梳理
学习python的进程和线程以来,对这两个概念一直都处于模糊状态,所以决定花点时间好好学习一下这块知识.以下是我自己在学习过程中形成的一些疑问以及搜集的一些相应的比较好的答案,整理如下,方便复习自查. ...
- Flutter 与 Android 的交互
https://juejin.im/post/5cd91de4518825686b120921 https://juejin.im/entry/5b64292be51d451995676398