责任链模式

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。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. Linux下检查是否安装过某软件包

    1.rpm包安装的,可以用 rpm -qa 看到,如果要查找某软件包是否安装,用 rpm -qa | grep "软件或者包的名字" 2.以deb包安装的,可以用 dpkg -l ...

  2. Android 面试题(经典)

    1.Actvity的生命周期,生命周期中的onCreate与onResume有什么区别 Activity的生命周期有:onCreate,onStart,onRestart,onResume,onPau ...

  3. 连续多行输入--C++ 中字符串标准输入的学习及实验(续篇)

      编程中常常会用到连续多行输入的情况,如果事先知道要输入多少行的话,可以直接定义一个变量,然后用循环就可以实现了,但有时候事先并不知道,要输入多少行,于是就可以用到输入流碰到文件终止符的情况了,具体 ...

  4. yeoman开始项目

    使用 yeoman 构建项目之前,你需要安装这两个环境:node,ruby. 为什么需要使用node?因为我们需要使用grunt自动化工具,而grunt工具则是依赖node. 为什么需要使用ruby? ...

  5. Hbase总结(一)-hbase命令,hbase安装,与Hive的区别,与传统数据库的区别,Hbase数据模型

    Hbase总结(一)-hbase命令 下面我们看看HBase Shell的一些基本操作命令,我列出了几个常用的HBase Shell命令,如下: 名称 命令表达式 创建表 create '表名称', ...

  6. 在oracle中where 子句和having子句中的区别

    在oracle中where 子句和having子句中的区别 1.where 不能放在GROUP BY 后面 2.HAVING 是跟GROUP BY 连在一起用的,放在GROUP BY 后面,此时的作用 ...

  7. 根据dwarfdump、Symbolicatecrash查找错误代码

    dSYM文件获取:1.build2.Archive 获取app UUID 命令:dwarfdump --uuid YourApp.app.dSYM 1.YourApp.app/YourApp2.You ...

  8. vim - 查找替换

    :%s/\<key_word_replaced\>/word_you_want_to_say/g

  9. 【C#学习笔记】调用C++生成的DLL

    首先用vs2010建立win32项目,选择dll和空项目. 头文件add.h extern "C" __declspec(dllexport) int add(int a,int ...

  10. 云计算服务模型,第 1 部分: 基础架构即服务(IaaS)

    英文原文:Cloud computing service models, Part 1: Infrastructure as a Service 本文介绍三个云类别中的第一个:基础架构即服务(infr ...