应用场景

http web请求处理,请求过来后将经过转码、解析、参数封装、鉴权等一系列的处理(责任),而且要经过多少处理是可以灵活调整的

那么该怎么做呢?

将所有的处理都写在一个类中行不行呢?

分成多个类又该如何灵活的组合在一起呢?

简单示例

Request类:

public interface Request{

//do something...

}

复制代码

ResponsibilityChain类:

public class ResponsibilityChain{

private List responsibilityList = new ArrayList<>();

private Integer index = 0;

public void process(Request request){

if (this.index < responsibilityList.size()) {

this.responsibilityList.get(index++).process(request, this);

}

}

/** 加入链中 */

public void register(Responsibility responsibility){

this.responsibilityList.add(responsibility);

}

}

复制代码

Responsibility接口:

public interface Responsibility{

void process(Request request, ResponsibilityChain chain);

}

复制代码

Responsibility实现类:

public class ResponsibilityA implements Responsibility{

@Override

public void process(Request request, ResponsibilityChain chain){

System.out.println("转码");

chain.process(request);

}

}

复制代码

public class ResponsibilityB implements Responsibility{

@Override

public void process(Request request, ResponsibilityChain chain){

System.out.println("解析");

chain.process(request);

}

}

复制代码

public class ResponsibilityC implements Responsibility{

@Override

public void process(Request request, ResponsibilityChain chain){

System.out.println("参数封装");

chain.process(request);

}

}

复制代码

public class ResponsibilityD implements Responsibility{

@Override

public void process(Request request, ResponsibilityChain chain){

System.out.println("鉴权");

chain.process(request);

}

}

复制代码

测试类:

public class Test{

public static void main(String[] args){

ResponsibilityChain chain = new ResponsibilityChain();

chain.register(new ResponsibilityA());

chain.register(new ResponsibilityB());

chain.register(new ResponsibilityC());

chain.register(new ResponsibilityD());

chain.process(new Request() {

});

}

}

复制代码

类图:

责任链模式

定义

所有的处理者,都加入到这个链式,一个处理完后,转给下一个

或者说每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者

抽象出责任接口,具体责任逻辑实现接口

根据处理过程需要,将具体实现组合成链

使用者使用链

典型的代表:Filter、Interceptor

意图

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止

主要解决问题

职责链上的处理者负责处理请求,客户端只需要将请求发送到职责链上就行了,不需要关系处理的细节和请求的传递,请求的发送者和处理者解耦了

何时使用

系统已经有一个由处理者对象组成的链,这个链可能有合成模式给出

有多于一个的处理者对象会处理一个请求,而且事先并不清楚到底由哪一个处理者对象处理一个请求,处理者对象是动态确定的

系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定哪一个处理者对象会处理该请求

处理一个请求的处理者对象集合需要动态的指定时

优缺点

优点:

发送者和接收者解耦,低耦合

简化了对象。使得对象不需要知道链的结构

通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任

增加新的请求处理类很方便

缺点:

不能保证请求一定被接收

系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用

可能不容易观察运行时的特征,有碍于除错

类图如下:

涉及到的角色:

抽象处理者(Handler)角色:定义一个处理请求的接口,如果需要,接口可以定义出一个方法,以设定和返回对下家的引用,这个角色通常由一个抽象类或者接口实现

具体处理者(ConcreteHandler)角色:具体处理者接收到请求后,可以选择将请求处理掉,或者传给下一个;具体处理者持有对下一个的引用,因此如果需要,具体处理者可以访问下一个

代码示例:

Handler类:

public abstract class Handler{

protected Handler successor;

/** 调用此方法处理请求 */

public abstract void handlerRequest();

/** 取值方法 */

public Handler getSuccessor(){

return successor;

}

/** 调用此方法设置下一个 */

public void setSuccessor(Handler successor){

this.successor = successor;

}

}

复制代码

ConcreteHandler类:

public class ConcreteHandler1 extends Handler{

@Override

public void handlerRequest(){

if (getSuccessor() != null) {

System.out.println("请求传递到下一个:" + getSuccessor().getClass().getName());

getSuccessor().handlerRequest();

} else {

System.out.println("请求在ConcreteHandler1被处理了");

}

}

}

复制代码

public class ConcreteHandler2 extends Handler{

@Override

public void handlerRequest(){

if (getSuccessor() != null) {

System.out.println("请求传递到下一个:" + getSuccessor());

getSuccessor().handlerRequest();

} else {

System.out.println("请求在ConcreteHandler2被处理了");

}

}

}

复制代码

客户端:

public class Client{

static private Handler handler1;

static private Handler handler2;

public static void main(String[] args){

handler1 = new ConcreteHandler1();

handler2 = new ConcreteHandler2();

handler1.setSuccessor(handler2);

handler1.handlerRequest();

}

}

复制代码

类图:

击鼓传花的故事

击鼓传花是一种热闹而又紧张的饮酒游戏,在酒宴上宾客依次坐定,由一人击鼓,开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在谁手里,谁就开始饮酒了;下面以《红楼梦》中击鼓传花的故事,写一个小例子:

抽象接口Player类:

public abstract class Player{

private Player player;

/** 需要执行酒令的请求 */

abstract public void handlerRequest(int index);

/** 设置下一个传花人 */

public void setPlayer(Player player){

this.player = player;

}

/** 将花传给下一家,如果没有就结束 */

public void next(int index){

if (player != null) {

player.handlerRequest(index);

} else {

System.out.println("传花结束");

}

}

}

复制代码

参与击鼓传花的人:

public class JiaMu extends Player{

public JiaMu(Player player){

this.setPlayer(player);

}

@Override

public void handlerRequest(int index){

if (index == 1) {

System.out.println("贾母执行酒令");

} else {

System.out.println("贾母将花传给下一个");

next(index);

}

}

}

复制代码

public class JiaShe extends Player{

public JiaShe(Player player){

this.setPlayer(player);

}

@Override

public void handlerRequest(int index){

if (index == 2) {

System.out.println("贾赦执行酒令");

} else {

System.out.println("贾赦将花传给下一个");

next(index);

}

}

}

复制代码

public class JiaZheng extends Player{

public JiaZheng(Player player){

this.setPlayer(player);

}

@Override

public void handlerRequest(int index){

if (index == 3) {

System.out.println("贾政执行酒令");

} else {

System.out.println("贾政将花传给下一个");

next(index);

}

}

}

复制代码

public class JiaBaoYu extends Player{

public JiaBaoYu(Player player){

this.setPlayer(player);

}

@Override

public void handlerRequest(int index){

if (index == 4) {

System.out.println("贾宝玉执行酒令");

} else {

System.out.println("贾宝玉将花传给下一个");

next(index);

}

}

}

复制代码

public class JiaHuan extends Player{

public JiaHuan(Player player){

this.setPlayer(player);

}

@Override

public void handlerRequest(int index){

if (index == 5) {

System.out.println("贾环执行酒令");

} else {

System.out.println("贾环将花传给下一个");

next(index);

}

}

}

复制代码

击鼓者:

public class DrinkingGame{

static private Player player;

public static void main(String[] args){

player = new JiaMu(

new JiaShe(

new JiaZheng(

new JiaBaoYu(

new JiaHuan(null)))));

//设置第四个执行酒令

player.handlerRequest(4);

}

}

复制代码

类图:

击鼓传花java_击鼓传花联想到了Java设计模式:责任链模式相关推荐

  1. 玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式

    命令模式 示例 改进代码 命令模式 定义 意图 主要解决问题 何时使用 优缺点 玉帝传美猴王上天 命令模式和策略模式的区别 示例 系统需要设计一个命令行界面,用户可输入命令来执行某项功能,系统的功能会 ...

  2. 迭代器 java_百战程序员:Java设计模式之迭代器模式

    迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作也放在集合对象中,但这样的话,集合对象就承担太多的责任了,面向对 ...

  3. 花了30天才肝出来,史上最全面Java设计模式总结,看完再也不会忘

    本文所有内容均节选自<设计模式就该这样学> 序言 Design Patterns: Elements of Reusable Object-Oriented Software(以下简称&l ...

  4. 【2021最新】大佬花了半个月整理出来的Java后端学习路线,果断收藏了!

    要成为一个符合 BAT.TMD 大厂要求的后端技术工程师,到底需要学哪些技术?后端技术学习路线是怎样的? 学习路线 话不多说,直接上刚画完的后端技术学习路线思维导图框架: ​ 图中的每一个节点都可以点 ...

  5. 联易融Java社招一面

    一:联易融Java社招一面 1:项目 主要问你负责什么模块,做什么业务,然后问下公司的项目架构.这个比较简单,只要把平时做过的说出来都还好. 2:Java基础 String类为什么不可以被继承? 多线 ...

  6. 有N个小朋友围成一圈玩击鼓传花游戏,将小朋友编号为1~N,从1号开始传花,每次传3个,拿到花的小朋友表演节目后退出,扔给后一位没有表演的同学,求同学们的表演次序?

    有N个小朋友围成一圈玩击鼓传花游戏,将小朋友编号为1~N,从1号开始传花,每次传3个,拿到花的小朋友表演节目后退出,扔给后一位没有表演的同学,求同学们的表演次序? 例如:5个小朋友,从1号开始传花,第 ...

  7. 由QQ文件中转站超快速上传联想到

    今天向QQ文件中转站上传了两个文件,一个30M,一个60M,都发现上传时间仅为1s, 猜想了一下,这里应该是有算法的,如果服务器上以及同样的文件了,就不需要用户再上传,而是直接给出文件链接,这样既减轻 ...

  8. 【SpringBoot学习】5、SpringBoot 实现文件上传,图片上传并显示功能

    SpringBoot 实现文件上传,图片上传并显示功能 我先看一下<颈椎病康复指南>再给大家说怎么实现的这两个功能,毕竟只是一个新手,解决这种复杂点的问题(相对而言),还是需要花费大量时间 ...

  9. vue动态路由传参---query传参和params传参

    当一个页面跳转到另一个页面时,组件结构相同,只是内容不同且地址栏后缀不同 ,这个地址栏的后缀就是参数,根据不同参数渲染不同的内容,这个跳转就叫路由传参. 当项目中组件间通过路由跳转,有时,我们需要传递 ...

最新文章

  1. 使用PyTorch从零开始实现YOLO-V3目标检测算法 (四)
  2. UVA 11401 - Triangle Counting
  3. python调用父类构造函数需要放在第一句吗_Python继承和调用父类构造函数
  4. java 关于日期的操作
  5. SVN工作笔记005---TortoiseSVN SendRpt.exe not found解决方案
  6. [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)
  7. 非纯 []!()输出 始皇帝 推导过程
  8. Eclipse中集成SVN
  9. 【VS开发】VS2010 MFC中控件、对话框等背景颜色动态修改的方法
  10. 【Matlab学习笔记】【图像滤波去噪】中值滤波
  11. javascript 计时器,消失计时器
  12. 各省份的车牌简称 备案地区的简称
  13. 0基础可以考CPDA数据分析师证书吗
  14. 三菱触摸屏通讯错误_s7-200和三菱触摸屏通讯的问题
  15. 小米4 android6.01的开发者模式开启方法
  16. 你真正付出了全部努力了吗?
  17. Ubuntu cd 命令
  18. mysql校对集_MySQL校对集问题的教程
  19. 【约束优先级问题二】动态高度cell
  20. Matlab里关于T2F/F2T/lpf.m函数调用应注意的问题及函数修改

热门文章

  1. 我是一棵小草我要寻觅春天
  2. vue 本地搜索 js实现本地数据搜索 el-select 模糊搜索
  3. Js中的const关键字
  4. 广州.NET微软技术俱乐部休闲活动 - 每周三五晚周日下午爬白云山活动
  5. 口才技巧|应对不同的人的口才技巧
  6. 知到山东理工c语言答案,山东理工大学C语言实验.doc
  7. 搜狗SEO工具批量查询搜狗收录页面
  8. Android: .java文件转.dex和java字节码
  9. mysql limit offset 原理分析与使用
  10. 牛客每日练习----逆序对,星图,小周的曲射炮