我的Java设计模式-责任链模式
今天来说说程序员小猿和产品就关于需求发生的故事。前不久,小猿收到了产品的需求。
产品经理:小猿,为了迎合大众屌丝用户的口味,我们要放一张图,要露点的。
小猿:......露点?你大爷的,让身为正义与纯洁化身的我做这种需求,还露点。
产品经理:误会误会,是放一张暴露一点点的,尺寸不大。
小猿:尼玛~能说清楚些吗,需求模棱两可的。不干,我要上报boss。
产品经理也一阵无语,这豆丁的事还上报boss。话说这上报也得走程序是吧,技术经理就不干了,“凭什么要跳过我,得经过我才能到boss”。咦~这一层一层上报就涉及到这次的责任链模式。
一、责任链模式
定义
创建多个对象,使这些对象形成一条链,并沿着这条链传递请求,直到链上的某一个对象决定处理此请求。
特点
1)接收请求的对象连接成一条链,对象之间存在层级关系。
2)这些对象可处理请求,也可传递请求,直到有对象处理该请求。
UML

责任链模式涉及到的角色如下所示:
- 抽象处理者角色:定义了处理请求的接口或者抽象类,提供了处理请求的的方法和设置下一个处理者的方法。
- 具体处理者角色:实现或者继承抽象这角色,具体逻辑根据实际的架构来定,后面会提到。
二、实战
先来看抽象处理者角色代码:
public abstract class Handler {
private Handler nextHandler;
private int level;
public Handler(int level) {
this.level = level;
}
// 处理请求传递,注意final,子类不可重写
public final void handleMessage(Demand demand) {
if (level == demand.demandLevel()) {
this.report(demand);
} else {
if (this.nextHandler != null) {
System.out.println("事情太严重,需报告上一级");
this.nextHandler.handleMessage(demand);
} else {
System.out.println("我就是boss,没有上头");
}
}
}
public void setNextHandler(Handler handler) {
this.nextHandler = handler;
}
// 抽象方法,子类实现
public abstract void report(Demand demand);
}
在抽象处理者角色定义了处理请求的抽象方法,以及下一级传递的对象方法,重点在handleMessage处理请求传递的方法,下面会解释为什么要这样写,继续往下看。
下面是具体处理者角色,继承抽象处理者角色,在我们情景中有两个具体处理者,分别是技术经理和boss。
// 技术经理
public class TechnicalManager extends Handler {
public TechnicalManager() {
super(1);
}
@Override
public void report(Demand demand) {
System.out.println("需求:" + demand.detail());
System.out.println(getClass().getSimpleName() + ":小猿我挺你,这个需求不干");
}
}
// boss
public class Boss extends Handler {
public Boss() {
super(2);
}
@Override
public void report(Demand demand) {
System.out.println("需求:" + demand.detail());
System.out.println(getClass().getSimpleName() + ":你们打一架吧,打赢的做决定");
}
}
可以看到具体处理者的代码很简洁,重写了report方法,实现各自的业务逻辑,这都归功于父类中handleMessage这个方法。
两个角色都定义好了,来看客户端如何实现:
public class Client {
public static void main(String[] args) {
Demand demandA = new DemandA(); // 请求等级低
Demand demandB = new DemandB(); // 请求等级高
Boss boss = new Boss();
TechnicalManager technicalManager = new TechnicalManager();
technicalManager.setNextHandler(boss); // 设置下一级
technicalManager.handleMessage(demandA);
System.out.println("============================");
technicalManager.handleMessage(demandB);
}
}
可以看到在客户端中的重点是设置下一级的处理者,这样多个处理者对象就会形成一条链。运行客户端,结果如下:
需求:加一张露一点点的图
TechnicalManager:小猿我挺你,这个需求不干
============================
需求:加一张露一点点的图
TechnicalManager:事情太严重,需报告上一级
Boss:你们打一架吧,打赢的做决定
从结果可以看到,级别低的请求技术经理自己处理,级别高的传递给了下一级的Boss,这样就形成一条链,而这也是责任链的核心所在。注意,在请求的传递过程中,请求是不会发生变化的。需求不会从“加一张露一点点的图”变成了“加一张露点的图”,这等着boss请到办公室喝茶吧。
三、扩展
责任链+模板方法
回头看看上面的代码,抽象类中定义了几个方法,一个是final修饰的handleMessage,一个是抽象方法report,还有一个是setNextHandler。这刚好是模板方法模式中的三个基本方法,分别是具体方法(抽象类声明并实现,子类不实现)、抽象方法(抽象类声明,子类必须实现)、钩子方法(抽象类声明并实现,子类可扩展)。handleMessage方法加了final修饰,子类不可重写,而handleMessage正是把传递请求工作交给父类Handler,子类不需要处理传递的工作。而report则是抽象方法,子类必须重写该方法,子类处理请求的业务逻辑。setNextHandler是钩子方法,在这里我们并没有实现。
这样结合模板方法模式的好处在哪?首先加了handleMessage方法,把请求的传递判断从子类中剥离出来,让子类在report方法中专心处理请求的业务逻辑,做到了单一职责原则。再者是子类的实现变得简单了,不需要进行传递的判断,非常有利于快速扩展。
责任链模式VS观察者模式
观察者模式我在之前有些过,不了解的可以先看看。责任链模式和观察者模式存在一个共同点,就是传递责任链模式是一级一级的传递,形成一条链,链节点(处理者)之间是存在传递关系的。而观察者模式的被观察者向观察者们的传递,并不是具体观察者之间的传递,观察者之间是不存在关联的。拿小猿的经历来说,在责任链模式中是请求从技术经理到boss,有层级关系,而对于观察者模式是从被观察者小猿发出,作为观察者的技术经理和boss都会收到小猿的通知,是扩散式的,技术经理和boss并没有层级关系。这是责任链模式和观察者模式的区别,也是责任链模式的核心。
四、责任链模式的优缺点
优点
1)降低耦合度:客户端不需要知道请求由哪个处理者处理,而处理者也不需要知道处理者之间的传递关系,由系统灵活的组织和分配。
2)良好的扩展性:增加处理者的实现很简单,只需重写处理请求业务逻辑的方法。
缺点
1)请求会从链头发出,直到有处理者响应,在责任链比较长的时候会影响系统性能。
2)请求递归,调试排错比较麻烦。
总结
责任链模式在实际项目中可以用到的地方还是比较多的,比如会员等级系统,会员等级之间构成一条链,用户发起一个请求,系统只要把请求分发到责任链模式的入口,直到传递到与用户会员匹配的等级,这样各个会员等级的业务逻辑就会变成很清晰。这篇折腾了很久,主要是想把责任链的核心阐述清楚,让大家能够容易理解,也让我重新思考了责任链模式的核心。下一篇是“还没想好”,您的点赞和关注是我的动力哦,再会!
设计模式Java源码GitHub下载:https://github.com/jetLee92/DesignPattern
我的Java设计模式-责任链模式的更多相关文章
- 【设计模式】Java设计模式 - 责任链模式
[设计模式]Java设计模式 - 责任链模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 目录 [设计模式]Java设计模式 - 责 ...
- java 设计模式 -- 责任链模式
设计模式 – 责任链模式 介绍: 责任链模式是一种动态行为模式,有多个对象,每一个对象分别拥有其下家的引用.连起来形成一条链.待处理对象则传到此链上,在此链进行传递,且待处理对象并不知道此会被链上的哪 ...
- Java设计模式-责任链模式
提出问题: 最初接触责任链模式就是在struts2中,在当时学的时候看了一眼,大概知道了原理,最近在复习,模拟struts2,说是模拟只是大体模拟了struts2的工作流程,很多东西都是写死的,只是为 ...
- Java设计模式の责任链模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...
- Java设计模式-责任链模式(Chain of Responsibility)
接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求.但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任 ...
- Java设计模式—责任链模式
责任链模式的定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 责任链模式的重点是在"链& ...
- 浅谈Python设计模式 -- 责任链模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 之前在最开始就聊了Python设计模式有三种,其中关于创建型和结构型设计模式基本 ...
- Java与设计模式-责任链模式
责任链模式属于行为型设计模式之中的一个,怎么理解责任链?责任链是能够理解成数个对象首尾连接而成,每个节点就是一个对象.每个对象相应不同的处理逻辑,直至有一个对象响应处理请求结束.这一种模式成为责任链模 ...
- php 23种设计模式 - 责任链模式
责任链模式 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行 ...
随机推荐
- CSS样式中常用的字体名称
css中引入字体: @font-face { font-family: "AncientWar"; src: url('style/css/fonts/AncientWar.ttf ...
- 使用autoc js生成文章目录(侧边)导航栏
介绍: autocjs 是一个专门用来生成文章目录(Table of Contents)导航的工具.autocjs 会查找文章指定区域中的所有 h1~h6 的标签,并自动分析文章的层次结构,生成文章的 ...
- 跨域资源共享 CORS 详解(转)
add by zhj: 公司在一个web产品上,做前后端分离,前后端提供独立的服务,使用不同的域名,通过http进行交互,在 前端,会涉及到跨域访问的问题,前端使用了CORS,后端同时需要做相应修改, ...
- mysql将查询出来的一列数据拼装成一个字符串
使用GROUP_CONCAT函数. SELECT GROUP_CONCAT(查询的字段 separator ',') FROM table
- 01_Linux安装
一.VMware创建一个虚拟机 下一步 .下一步 .下一步 ..前方高能 二.安装CentOS 6.7 next -> 选择 中文简体 -> 美式键盘,直接下一步 ,一直下一 ...
- 解决苹果电脑(mac)管理员账户变成了普通用户后不能解锁用户与群组的问题
亲们,我先说说前因,然后再说一下解决方法. 前因 今天不知怎么就想把苹果电脑原来的名字给改一下,于是就做了下面的操作(你们不要这样做) 1.系统偏好设置→用户与组群→当前管理员用户→(右键)高级选项 ...
- Designing Data-Intensive Applications
下面是这本书序言中的大部分内容,本人的英文水平有限,有理解不到位的地方还请大家指教,这算是自己对这本书的读书笔记和总结. 数据是当今系统设计中许多挑战的中心,一些难以解决的问题如系统的可扩展性,一致性 ...
- c# 实现mysql事务
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- BZOJ 3881: [Coci2015]Divljak [AC自动机 树链的并]
3881: [Coci2015]Divljak 题意:添加新文本串,询问某个模式串在多少种文本串里出现过 模式串建AC自动机,考虑添加一个文本串,走到的节点记录下来求树链的并 方法是按dfs序排序去重 ...
- COGS 2479. [HZOI 2016]偏序 [CDQ分治套CDQ分治 四维偏序]
传送门 给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数. 对于100%的 ...