责任链模式

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。Tomcat中的Filter就是使用了责任链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现javax.servlet.Filter接口。

为了方便理解,责任链模式直接用马士兵老师中的一个例子来讲解,做下笔记也方便自己以后的复习查询:

我们有一个字符串String msg = ":):,<script>,敏感,被就业,网络授课";我们希望应用以下三个规则对字符串进行过滤和谐处理:

(1)将字符串中出现的"<>"符号替换成"[]"

(2)处理字符串中的敏感信息,将被就业和谐成就业

(3)将字符串中出现的":):"转换成"^V^";

字符串会依次运用这三条规则,对字符串进行处理,每个规则都有自己需要完成的责任和任务。

第一步:定义封装请求的类Request和封装处理结果响应的类Response

//封装请求的类Request
public class Request {
String requestStr; public String getRequest() {
return requestStr;
} public void setRequest(String request) {
this.requestStr = request;
} }
//封装响应信息的类Response
public class Response {
String responseStr; public String getResponse() {
return responseStr;
} public void setResponse(String response) {
this.responseStr = response;
} }

第二步:定义具有过滤功能的接口Filter,具体的过滤规则需要实现该接口

/*
* 定义接口Filter,具体的过滤规则需要实现这个接口,最后一个参数添加的意义是我们在Main函数中:
* fc.doFilter(request, response,fc);执行这一步的时候可以按照规则链条一次使用三个过滤规则对字符串进行处理
* 因为
*
*/
public interface Filter {
void doFilter(Request request,Response response,FilterChain chain);
}

第三步:定义具体的过滤处理规则

规则一

package com.bjsxt.dp.filter;

//处理字符串中的HTML标记
public class HTMLFilter implements Filter { public void doFilter(Request request, Response response,FilterChain chain) {
//将字符串中出现的"<>"符号替换成"[]"
request.requestStr=request.requestStr
.replace('<', '[').replace('>', ']')+
//后面添加的是便于我们观察代码执行步骤的字符串
"----HTMLFilter()";
chain.doFilter(request, response,chain);
response.responseStr+="---HTMLFilter()";
} }  

规则二

package com.bjsxt.dp.filter;

//定义的过滤敏感字眼的过滤规则
public class SensitiveFilter implements Filter{ public void doFilter(Request request, Response response,FilterChain chain) {
//处理字符串中的敏感信息,将被就业和谐成就业
request.requestStr=request.requestStr
.replace("被就业", "就业").replace("敏感", "")+
//后面添加的是便于我们观察代码执行步骤的字符串
" ---sensitiveFilter()";
chain.doFilter(request, response,chain);
response.responseStr+="---sensitiveFilter()";
} }

规则三:

package com.bjsxt.dp.filter;

//定义FaceFilter
public class FaceFilter implements Filter { public void doFilter(Request request, Response response, FilterChain chain) { //将字符串中出现的":):"转换成"^V^";
request.requestStr = request.requestStr.replace(":):", "^V^")
//后面添加的是便于我们观察代码执行步骤的字符串
+ "----FaceFilter()";
chain.doFilter(request, response, chain);
response.responseStr += "---FaceFilter()";
} } 

第四步:定义责任链FilterChain

package com.bjsxt.dp.filter;

import java.util.ArrayList;
import java.util.List; //过滤链条
public class FilterChain implements Filter{
//用List集合来存储过滤规则
List<Filter> filters = new ArrayList<Filter>();
//用于标记规则的引用顺序
int index=0;
//往规则链条中添加规则
public FilterChain addFilter(Filter f) {
filters.add(f);
//代码的设计技巧:Chain链添加过滤规则结束后返回添加后的Chain,方便我们下面doFilter函数的操作
return this;
}
public void doFilter(Request request,Response response,FilterChain chain){
//index初始化为0,filters.size()为3,不会执行return操作
if(index==filters.size()){
return;
}
//每添加一个过滤规则,index自增1
Filter f=filters.get(index);
index++;
//根据索引值获取对应的规律规则对字符串进行处理
f.doFilter(request, response, chain);
}
}

第五步:测试一下我们的代码

package com.bjsxt.dp.filter;

import java.util.ArrayList;
import java.util.List; //过滤链条
public class FilterChain implements Filter{
//用List集合来存储过滤规则
List<Filter> filters = new ArrayList<Filter>();
//用于标记规则的引用顺序
int index=0;
//往规则链条中添加规则
public FilterChain addFilter(Filter f) {
filters.add(f);
//代码的设计技巧:Chain链添加过滤规则结束后返回添加后的Chain,方便我们下面doFilter函数的操作
return this;
}
public void doFilter(Request request,Response response,FilterChain chain){
//index初始化为0,filters.size()为3,不会执行return操作
if(index==filters.size()){
return;
}
//每添加一个过滤规则,index自增1
Filter f=filters.get(index);
index++;
//根据索引值获取对应的规律规则对字符串进行处理
f.doFilter(request, response, chain);
}
}

运行结果:

^V^,[script],,就业,网络授课----HTMLFilter() ---sensitiveFilter()----FaceFilter()
response:---FaceFilter()---sensitiveFilter()---HTMLFilter()

代码可以使用Eclipse中设置断点,debug单步调试去验证,我们下面带着大家一块执行一下上面的代码。
(1)主函数中执行到fc.doFilter(request, response,fc);我们在此处设置断点(Eclipse设置断点的方式:在这行左面,双击那个竖边框的对应位置即可设置断点),现在的执行情况是下面这样,代码上面可以看到执行过程,现在停留在Main.main函数中。

(2)我们点击左上角的Step Into(F5)进入到doFilter(request,response,fc)中

现在执行位置在FilterChain.doFilter,依次执行代码,因为此时的index还是0,因此不可能执行return操作,跳过if代码块,调用索引值为0的规则HTMLFilter,index自增1,执行f.doFilter(request, response, chain);现在进入到了HTMLFilter类中的doFilter方法中

依次执行代码,对字符串请求进行处理,执行到chain.doFilter(request, response,chain)这一句,会再次进入FilterChain中的doFilter方法内

此时的index为1,仍然跳过if代码块执行下面的步骤,和上面一样,用索引值为1的规则进行处理,index自增1现在变成2了。执行f.doFilter(request, response, chain);会进入到SensitiveFilter中的doFilter方法执行

第三个规则的应用和前两个一致,直接给出执行到FaceFilter类中的doFilter方法的结果截图

现在执行到if判断,index的值为3,满足判断条件返回,上图中最上面的函数退栈,回到FaceFilter.doFilter函数中执行response.responseStr += "---FaceFilter()";这就是我们运行结果中response中的第一部分。函数会依次退栈,response不断添加已经做过处理的规则的信息response.responseStr+="---sensitiveFilter()";response.responseStr+="---HTMLFilter()";最终回到Main.main函中打印reponse信息

运行过程用下图表示:

Java设计模式系列之责任链模式的更多相关文章

  1. 重学 Java 设计模式:实战责任链模式「模拟618电商大促期间,项目上线流程多级负责人审批场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 场地和场景的重要性 射击

  2. 《java设计模式》之责任链模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...

  3. Java设计模式学习记录-责任链模式

    前言 已经把五个创建型设计模式和七个结构型设计模式介绍完了,从这篇开始要介绍行为型设计模式了,第一个要介绍的行为型设计模式就是责任链模式(又称职责链模式). 责任链模式 概念介绍 责任链模式是为了避免 ...

  4. Java设计模式13:责任链模式

    前言 来菜鸟这个大家庭10个月了,总得来说比较融入了环境,同时在忙碌的工作中也深感技术积累不够,在优秀的人身边工作必须更加花时间去提升自己的技术能力.技术视野,所以开一个系列文章,标题就轻松一点叫做最 ...

  5. 《JAVA设计模式》之责任链模式(Chain of Responsibility)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...

  6. Java设计模式十九——责任链模式

    责任链模式 老李的苦恼 每个人在出生的时候,都早已在暗中被标好了三六九等. 老李是一名建筑工地的木匠,和大多数生活在社会最底层的农民工一样,一辈子老实本分,胆小怕事.在他们的心中,谁当老爷都没有区别, ...

  7. Java设计模式之《职责链模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6530089.html 职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形 ...

  8. Python使用设计模式中的责任链模式与迭代器模式的示例

    Python使用设计模式中的责任链模式与迭代器模式的示例 这篇文章主要介绍了Python使用设计模式中的责任链模式与迭代器模式的示例,责任链模式与迭代器模式都可以被看作为行为型的设计模式,需要的朋友可 ...

  9. 【java设计模式】之 责任链(chain of resposibility)模式

    责任链模式,顾名思义,就是一条链.这个链到底是怎么运行的呢?它主要是将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给 ...

随机推荐

  1. windows和mac下分别配置虚拟主机

    windows下配置 1.找到apache的配置文件,httpd.conf 2.找到 LoadModule rewrite_module modules/mod_rewrite.so 去掉前边的# 3 ...

  2. [POJ2398]Toy Storage(计算几何,二分,判断点在线段的哪一侧)

    题目链接:http://poj.org/problem?id=2398 思路RT,和POJ2318一样,就是需要排序,输出也不一样.手工画一下就明白了.注意叉乘的时候a×b是判断a在b的顺时针还是逆时 ...

  3. Android studio编译之后显示中文乱码的问题解决办法

    在build.gradle文件中加上 android {compileOptions.encoding = "GBK"}

  4. 带你走进EJB--那些跟EJB容器相关的那些Java概念

    最近在对EJB的相关内容进行总结,在总结的过程中发现对容器的概念并不是很理解,因为EJB本身就是一个容器,但是容器到底是用来做什么的?它跟我们之前所了解的组件,框架,包,类等都有什么关系?接下来主要是 ...

  5. linux文件和目录基本操作

    比较特殊的目录: .   代表此层目录 .. 代表上一层目录 - 代表前一个工作目录 -代表当前用户身份所在的主文件夹 -account 代表account用户所在主文件夹 1.目录相关操作 cd切换 ...

  6. Qt之QTableView添加复选框(QAbstractTableModel)

    简述 使用QTableView,经常会遇到复选框,要实现一个好的复选框,除了常规的功能外,还应注意以下几点: 三态:不选/半选/全选 自定义风格(样式) 下面我们介绍一下常见的实现方式: 编辑委托. ...

  7. BZOJ3218: a + b Problem

    题解: 先做60分... 考虑最小割,连边容量为需要付出的代价.不妨设在s割为黑色,t割为白色. (s,i,b[i])(i,t,w[i]) 关于奇怪,因为不是按份数来的.所以我们这样建图: (i,i+ ...

  8. SQL Server索引怎么用

    什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的速度,汉语字(词)典一般都有按拼音. ...

  9. WebView线性进度条

    参考:http://www.cnblogs.com/hubli/p/4835549.html APP会跳转网页时候,请参考:http://blog.csdn.net/raphael55/article ...

  10. Android 开发问题集合

    1.屏幕横.竖切换 修改“AndroidManifest.xml”的android:screenOrientation 一般需要:landscape.portrait 2.修改应用名字 修改“Andr ...