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的情况,决定学习一下责任链模式. 一.什么样的场景下会选择用责任链模式 我们在进行业务逻辑判断时,需 ...
随机推荐
- 「模拟赛20191019」C 推式子+贪心+树状数组
题目描述 给定一棵\(n\)个点的有根树,根节点编号为\(1\),点有点权. 定义\(d(v)\)表示\(v\)到\(1\)的路径上的边数. 定义\(f(v,u)\)在\(v<u\)且\(v\) ...
- LeetCode 556. 下一个更大元素 III(Next Greater Element III)
556. 下一个更大元素 III 556. Next Greater Element III 题目描述 给定一个 32 位正整数 n,你需要找到最小的 32 位整数,其与 n 中存在的位数完全相同,并 ...
- python 之 Django框架(ORM常用字段和字段参数、关系字段和和字段参数)
12.324 Django ORM常用字段 .id = models.AutoField(primary_key=True):int自增列,必须填入参数 primary_key=True.当model ...
- python实战项目 — selenium登陆豆瓣
利用selenium 模仿浏览器,登陆豆瓣 重点: 1. 要设置好 chromedriver配置与使用, chromedriver.exe 和 Chrome的浏览器版本要对应, http://chro ...
- Typora语法使用说明
目录 文本 标题 超链接 锚点 列表 引用 插入图片 脚注 代码 LaTex公式 插入表情 任务列表 高亮 注脚 文本 代码: *斜体* **粗体** ***斜体加粗体*** ~~删除线~~ < ...
- Python字符串格式化方式之format
format方式是在Python3引入了一个新的字符串格式化的方法,并且随后支持了Python2.7.这个新的字符串格式化方法摆脱了%操作符并且使得字符串格式化的语法更规范了.现在时候通过调用字符串对 ...
- js加减乘除函数
经常用到算数的时候,可以直接用:// 除法函数function accDiv(arg1, arg2) { var t1 = 0, t2 = 0, r1, r2; try { t1 = arg1.toS ...
- 记录用到的mssql的几个方法
1.RIGHT ( character_expression , integer_expression ) 返回字符串中从右边开始指定个数的字符 character_expression 字符或二进制 ...
- Windows系统中环境变量不展开的问题
Windows系统中环境变量不展开的问题 问题现象:Windows.System32等系统目录里命令,无法通过Path搜索路径来执行.查看Path环境变量结果如下: D:\>echo %Path ...
- mysql 设置局域网内可访问
今天同事要连我电脑的数据库 我以为只要127.0.0.1 可以访问就是 运行通过ip访问的... 然而并不是..这里记录下方法 1.打开命令行 进入你电脑的 mysql的bin 目录下 mys ...