面试官:什么是责任链模式?
前言
只有光头才能变强。
文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y
最近在看项目代码的时候发现「责任链模式」,于是想花点时间来写写什么是责任链模式。
不知道大家是怎么学习设计模式的,一般我都是用到的时候,或者接触到的时候才会去学。否则感觉学完就很容易就忘掉了,不能理解为什么要使用设计模式(因为没有真实的场景给我去使用)。
在之前我已经更新说几篇设计模式的文章了,我觉得写得「还行」,有兴趣的同学可以到我的GitHub上,关键字搜索「设计模式」,就能找到对应的文章。
不得不说,我现在负责项目的代码我常常会感叹:**这代码怎么这么骚啊!**项目里边用到了很多的设计模式,在最开始看的时候会很费劲(因为之前没学),但维护起来是真的方便。
一、什么是责任链模式?
在说责任链模式之前,我们先来聊聊「过滤器」。
过滤器相信大家都肯定学过了,在最开始学Servlet的时候我们会学到Filter
。等学到Struts2的时候,我们会学到Interceptor
。等学到SpringMVC的时候,我们会学到HandlerInterceptor
。
但无论学哪个框架,我们发现是最终其实它还是做Filter
这么一件事。说白了就是:
- 把所有的过滤器都放在FilterChain里边,依次执行每个过滤器。
在我的GitHub对Filter,HandlerInterceptor,Interceptor都有讲到,如果想要复习的同学不妨进去搜索关键字「过滤器」「Struts2」「SpringMVC」
为什么看责任链模式要聊「过滤器」呢?后面会讲到,不要着急。
1.1 干掉敖丙和鸡蛋
举个例子:把我们的正常请求想象成一堆的杂物,里边有米豆,有鸡蛋,有敖丙公仔玩具等等一些杂物。
现在我们想要最后得到的是米豆,鸡蛋和敖丙玩具都被过滤掉。于是我们就可以搞两个滤网,把敖丙玩具和鸡蛋给过滤掉。
以最快的方式,我们可以写if
来把这个需求给搞掂,下面上代码。
一个请求,我们使用Request
对象来表示:
public class Request {// 请求的数据private String data;public String getData() {return data;}public void setData(String data) {this.data = data;}
}
针对请求,我们肯定是有一个接口处理请求的啦,我们使用Handler
来表示:
public class Handler {public void handlerRequest(Request request) {// 得到请求的数据String data = request.getData();if (data.contains("鸡蛋")) {filterEgg(data);}if (data.contains("敖丙工具")) {filterAoBing(data);}// 我到这里就能拿到米豆了。}private void filterAoBing(String data) {//doSomething}private void filterEgg(String data) {//doSomething}
}
上面的代码大家不知道熟不熟悉,反正我就很熟悉,很多时候我就是这样写代码的(在现实里边很多代码就是这样的)。
1.2 如何更加优雅干掉敖丙和鸡蛋?
在某年某月产品过来告诉我,需要新增一种类型想要过滤的「白菜」
在某年某月产品过来告诉我,需要新增一种类型想要过滤的「鸡腿」
在某年某月产品过来告诉我,需要新增一种类型想要过滤的「鸡头」
于是我们的Handler处理就可能「膨胀」起来了,可能是这样?
public class Handler {public void handlerRequest(Request request) {// 得到请求的数据String data = request.getData();if (data.contains("鸡蛋")) {filterEgg(data);}if (data.contains("敖丙工具")) {filterAoBing(data);}if (data.contains("白菜")) {filterBaiCai(data);}if (data.contains("鸡头")) {filterJiTou(data);}if (data.contains("鸡腿")) {filterJiTui(data);}// 我到这里就能拿到米豆了。}private void filterJiTou(String data) {//doSomething}private void filterJiTui(String data) {//doSomething}private void filterAoBing(String data) {//doSomething}private void filterEgg(String data) {//doSomething}
}
明显的是,如果处理的流程改动比较大的话(需要增删改其中的某个流程),那我每次都需要更改handlerRequest
的代码,增加/修改/删除一个if
和一个处理方法。
更加面向对象的方式是这样的:将每个处理的方式抽象成一个类,每个类各司其职。
无论是过滤敖丙还是过滤鸡蛋还是过滤米豆,做的事都是过滤。我们就可以将其抽象成接口。于是我们就有一个接口,多个实现类。
public interface Filter {// 过滤void doFilter(String data);
}class FilterEgg implements Filter {@Overridepublic void doFilter(String data) {//doSomething}
}class FilterAoBing implements Filter {@Overridepublic void doFilter(String data) {//doSomething}
}class FilterBaiCai implements Filter {@Overridepublic void doFilter(String data) {//doSomething}
}class FilterJiTou implements Filter {@Overridepublic void doFilter(String data) {//doSomething}
}
每个各司其职的Filter都有可能被执行,我们可以将其串成一条链,抽象一层对外只暴露一个方法来替代if
。于是我们可以写出一个FilterChain
类
public class FilterChain {List<Filter> filters = new ArrayList<>();public FilterChain() {filters.add(new FilterEgg());filters.add(new FilterAoBing());filters.add(new FilterBaiCai());filters.add(new FilterJiTou());}public void processData(String data) {for (Filter filter : filters) {filter.doFilter(data);}}
}
改造过后,我们的Handler
就长这个样子了:
public class Handler {public void handlerRequest(Request request) {// 得到请求的数据String data = request.getData();FilterChain filterChain = new FilterChain();// 处理数据filterChain.processData(data);}
}
如果我告诉你,这种的处理方式就是责任链模式,你会怎么想?
二、为什么责任链模式?
再来回顾一下,我做了些什么:
- 将处理的各个流程抽象为各个类(本来Handler里边有多个
if
和方法
) - 将多个类用
Chain
链起来,暴露一个方法给Handler使用 - done
下面我画了一张对比图:
是不是很简单?说到底还是抽象了一层(将每个处理抽象为一个类而已)。
那为什么要这样干?如果我要增加一个处理流程,我是得新增一个处理类,然后在链上增加相对应的类。操作也的确如此。
这不麻烦吗?要便捷的话,我还不如直接增加一个if
,一个处理方法来得方便呢。
用责任链模式的好处就是分工明确,解耦,容易维护。
- 将多个条件判定分散到各个的处理类上,相对于
if else
耦合性相对较低。 - 增加一个具体的
Handler
处理类,不会影响到BaseHandler
的代码
责任链模式的缺点:
- 项目里边会有多个具体Handler类(因为每种处理都抽象为一个类,所以会有多个类)
- 不好调试,初看代码时不好阅读。(对外只是一个
doChain
方法,而里边由多个处理类来组成,还得看相应的调用顺序)
三、再来聊聊责任链模式
我们从上面也可以看到责任链模式主要有以下特点:
- 一个Handler接口,多个Handler处理类
- 多个Handler处理类串起来形成一条链
有这两个特点我就称这些代码运用了责任链模式。在翻阅资料或者看书的时候,你可能会看到:“纯责任链和不纯责任链”
纯:请求执行到某个具体的Handler,该Handler要么自行处理然后结束请求,要么不处理继续往下给别的Handler执行。
不纯:请求执行到某个具体的Handler,该Handler自行处理了,还继续往下给别的Handler执行。
还有就是将各个具体的Handler串成一条链,这里边的实现会有各式各样的:
- 在我例子里是直接
new
出一个ArrayList,然后在构造方法里边代码手动add到ArrayList的 - 有可能会在代码里边每个具体Handler都会记录自己下一个Handler是谁
- 有可能将Handler的初始化放在XML上
- …//反正各种操作最终还是会将各个Handler串起来。
其实不必要在意纯和不纯的责任链模式,我们学设计模式是为了学它的思想。
四、看看JavaWeb的Filter
在文章最开头我就说了我们以前学过的Filter,其实Filter就是用了责任链模式。我们来简单看看代码:
我们在使用Filter过滤器的时候,要么在XML上配置<filter>
,要么在代码上写上注解@WebFilter(filterName = "",urlPatterns = "")
这些配置都会在Web容器启动的时候被读取,读完这些配置,会将你写的Filter过滤器加到FilterChain里边:
我们可以看到Filter接口下有很多都实现了doFilter
:
JavaWeb的Filter实际用到的也是责任链模式。
最后
设计模式本身不是一件很复杂的东西,像门面模式,模板方法模式都非常容易理解。学完了会有一种感觉:“啊?就这?”
重要的是学完能不能用到实际的工作中,这是非常难能可贵的。我们写代码按照自身的思维写if else
是非常简单的,而设计模式往往需要绕一个圈才能把功能实现。
但是,合理运用设计模式的代码是非常好维护的。如果你懂设计模式,那代码会看起来非常清晰。如果你不懂设计模式,你就会感叹“这代码是真的骚阿”(这就是我…)。
好好学习,希望有朝一日,别人看到我的代码,在背后说「这人写的代码是真的骚,牛逼阿」。
参考资料:
- 《设计模式之禅》
- https://www.cnblogs.com/tanshaoshenghao/p/10741160.html
涵盖Java后端所有知识点的开源项目(已有5.8K star):https://github.com/ZhongFuCheng3y/3y
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号「Java3y」。(微信搜Java3y即可关注)
-
面试官:什么是责任链模式?相关推荐
- 字节面试:什么是责任链模式?
微信搜索[三太子敖丙]关注这个贪财好色的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. 前言 面试经历 ...
- 轻松学习Java设计模式之责任链模式
我们的态度是:每天进步一点点,理想终会被实现. 前言 设计模式,可能很多人都是看到代码知道怎么回事,但是离开代码再让其说出来,估计就有点含糊其词了,包括我自己在内.Android中其实用到的设计模式也 ...
- 工作中常用的设计模式 -- 责任链模式
一般做业务开发,不太容易有大量使用设计模式的场景.这里总结一下在业务开发中使用较为频繁的设计模式.当然语言为 Java,基于 Spring 框架. 1 责任链模式(Chain of Responsib ...
- 【深入设计模式】责任链模式—责任链模式及责任链模式在源码中的应用
文章目录 1. 责任链模式 1.1 责任链模式简介 1.2 责任链模式结构 1.3 责任链模式示例 2. 责任链模式在源码中的应用 2.1 Servlet 中的责任链模式 2.2 Spring 中的责 ...
- 责任链模式在王者荣耀中的应用,妙!
程序员的成长之路 互联网/程序员/技术/资料共享 关注 阅读本文大概需要 7 分钟. 来自:blog.csdn.net/IT_charge/article/details/105011204/ # 简 ...
- 责任链模式 php,编程中的那些套路——关于责任链模式
该文章属于<编程中的那些经典套路--设计模式汇总>系列,并且以下内容基于语言PHP 今天来谈谈责任链模式,乍一听责任链模式好像很高级的一样,但是相信我,其实每位天朝的同学都十分熟悉这个模式 ...
- Chain of Responsibility 责任链模式 MD
责任链模式 简介 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链,请求在这个链上[传递],直到链上的某一个对象决定处理此请求.发出这个请求的客户 ...
- Java 责任链模式
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为 ...
- 设计模式之五 责任链模式(Chain of Responsibility)
2019独角兽企业重金招聘Python工程师标准>>> 一. 场景 相信我们都有过这样的经历: 我们去职能部门办理一个事情,先去了A部门,到了地方被告知这件事情由B部门处理: 当我们 ...
最新文章
- python读取excelsheet-python读取excel文件中所有sheet表格
- Silverlight 4 新特性之Silverlight as Drop Target
- poj-2828 Buy Tickets ***
- jQuery Mobile和UI合并组新项目,这波能赢么?
- android 获取phone实例,android – 可以通过sdk来实例化一个telephony.Phone对象吗?
- This blog has been cancelled for a long time
- Kudu报错:你的主机中的软件终止了一个已建立的链接
- 软件测试某公司面试题2014
- JavaScript ES5之Object.create函数详解
- 流媒体视频质量评价(单刺激连续质量评价方法)
- 软件界旷世之架:测试驱动开发(TDD)之争
- 解决使用Glide加载图片背景出现浅绿色
- Mybatis-查询处理一对一和一对多
- 依托数网星工业互联网平台构建能源管理平台,助力企业能耗结构优化
- 安卓逆向_3 --- 篡改apk名称和图标、修改包名实现应用分身、修改资源去广告、去除re管理器广告...
- 微服务架构深度解析与最佳实践 - 第七部分:全文总结与引用材料
- 那么这几天都是自己和工作上的事情比较零零散散
- 后台管理系统——登录功能
- 卡拉兹(Callatz)猜想
- FPGA经验谈系列文章——FPGA资源评估
热门文章
- 阿里云认证是什么?报考要什么条件?
- Springboot中国古代史在线学习网站 毕业设计-附源码260839
- Pixel2Mesh-Tensorflow2
- Linux十大常用命令
- 什么是政微助手?政微助手是干什么用的?
- 痞子衡嵌入式:深扒i.MXRTxxx系列ROM中集成的串行NOR Flash启动SW Reset功能及其应用场合...
- 如何用计算机自动回复微信,10分钟教你用Python实现微信自动回复功能
- 执著如泪,是滴入心中的破碎
- 关于若依框架多级菜单的设置
- Java线程的6种状态(NEW,RUNNABLE,BLOCKED,WAITING,TINED_WATING,TEMINATE)
- 字节面试:什么是责任链模式?