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的情况,决定学习一下责任链模式. 一.什么样的场景下会选择用责任链模式 我们在进行业务逻辑判断时,需 ...
随机推荐
- 在ensp上VLAN基础配置以及Access接口
什么是VLAN? 早期的局域网技术是基于总线型的结构,也就是说所有主机共享一条传输线路.这就带来了很多问题:冲突域和安全问题.为了避免冲突域,我们使用二层交换机.但想想,一台计算机在总线上传输数据的时 ...
- PHP反射API (转)
http://www.cnblogs.com/zyf-zhaoyafei/p/4922893.html 近期忙着写项目,没有学习什么特别新的东西,所以好长时间没有更新博客.我们的项目用的是lumen, ...
- CF13C Sequence(DP+离散化)
题目描述 给定一个序列,每次操作可以把某个数+1-1.要求把序列变成非降数列.求最少的修改次数. 输入输出样例 输入 #1 - 输出 #1 4 输入 #2 输出 #2 1 解题思路 这题是一道非常好题 ...
- C++—多态与继承
一.基本概念 1.类的继承,是新的类从已有类那里得到已有的特性.或从已有类产生新类的过程就是类的派生.原有的类称为基类或父类,产生的新类称为派生类或子类. 2.派生类的声明: class 派生类名:继 ...
- ssh常用操作
介绍ssh.sshpass.scp等linux下远程操作常用的命令 ssh 通过终端远程linux服务器的常用命令 ssh root@192.168.1.100 #以root用户链接到目标服务器,连通 ...
- 记录用到的mssql的几个方法
1.RIGHT ( character_expression , integer_expression ) 返回字符串中从右边开始指定个数的字符 character_expression 字符或二进制 ...
- activiti串行会签的使用
1.串行任务的配置 2.当任务走到串行会签节点时,会从你之前保存的流程变量中找集合(我这里设置的assigneeList),串行会签会根据这个集合设置一系列该节点的流程变量 3.结束条件的设置,若满足 ...
- 【开发笔记】- Linux命令大全
系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...
- 借助openpyxl处理excel
一次处理excel中,原计划是借助excel中自带的工具进行处理,然而看到需要处理的列要达到30+,后来放弃了,用Python处理或许是一个不错的选择. 需求: 表格中每一列数据都是一个随机值,但是已 ...
- 装饰器带类参数 & 一个函数应用多个装饰器
装饰器:不改变原函数的基础上,给函数增加功能的方式,称为装饰器 即:为已经存在的对象添加额外的功能 装饰器其实就是一个闭包,把一个函数当做参数后返回一个替代版的函数 decos.py:(装饰器的参数类 ...