博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java设计模式--责任链模式(Chain of Responsibility)
阅读量:4031 次
发布时间:2019-05-24

本文共 5766 字,大约阅读时间需要 19 分钟。

一、定义

转自:http://www.cnblogs.com/draem0507/p/3784130.html

在阎宏博士的《JAVA与模式》一书中开头是这样描述责任链(Chain of Responsibility)模式的:

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


在以下条件下可考虑使用Chain of Responsibility:
1 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
2 你想在不明确指定接受者的情况下,想过个对象中的一个提交一个请求。
3 可处理一个请求的对象集合应该被动态指定。

二、应用

转自:http://www.cnblogs.com/ysw-go/p/5432921.html

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

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

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

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

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

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

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

任务描述:有一个请求和一个响应,过滤器既要处理请求也要处理响应,所有过滤器先处理请求,请求处理完后,按处理请求的反顺序处理响应。

这个运行顺序很像堆栈,下面的实现就是靠的函数调用。

时序图如下:

【转自:http://blog.csdn.net/yueguanghaidao/article/details/7922414】

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

1 //封装请求的类Request 2 public class Request { 3     String requestStr; 4  5     public String getRequest() { 6         return requestStr; 7     } 8  9     public void setRequest(String request) {10         this.requestStr = request;11     }12     13 }
1 //封装响应信息的类Response 2 public class Response { 3     String responseStr; 4  5     public String getResponse() { 6         return responseStr; 7     } 8  9     public void setResponse(String response) {10         this.responseStr = response;11     }12     13 }

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

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

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

规则一

1 package com.bjsxt.dp.filter; 2  3 //处理字符串中的HTML标记 4 public class HTMLFilter implements Filter { 5  6     public void doFilter(Request request, Response response,FilterChain chain) { 7         //将字符串中出现的"<>"符号替换成"[]" 8         request.requestStr=request.requestStr 9                 .replace('<', '[').replace('>', ']')+10                 //后面添加的是便于我们观察代码执行步骤的字符串11                 "----HTMLFilter()";12         chain.doFilter(request, response,chain);13         response.responseStr+="---HTMLFilter()";14     }15 16 }

规则二

1 package com.bjsxt.dp.filter; 2  3 //定义的过滤敏感字眼的过滤规则 4 public class SensitiveFilter implements Filter{ 5  6     public void doFilter(Request request, Response response,FilterChain chain) { 7         //处理字符串中的敏感信息,将被就业和谐成就业 8         request.requestStr=request.requestStr 9                 .replace("被就业", "就业").replace("敏感", "")+10                 //后面添加的是便于我们观察代码执行步骤的字符串11                 " ---sensitiveFilter()";12         chain.doFilter(request, response,chain);13         response.responseStr+="---sensitiveFilter()";14     }15 16 }

规则三

1 package com.bjsxt.dp.filter; 2  3 //定义FaceFilter 4 public class FaceFilter implements Filter { 5  6     public void doFilter(Request request, Response response, FilterChain chain) { 7  8         //将字符串中出现的":):"转换成"^V^"; 9         request.requestStr = request.requestStr.replace(":):", "^V^")10                 //后面添加的是便于我们观察代码执行步骤的字符串11                 + "----FaceFilter()";12         chain.doFilter(request, response, chain);13         response.responseStr += "---FaceFilter()";14     }15 16 }

第四步:定义责任链FilterChain

1 package com.bjsxt.dp.filter; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 //过滤链条 7 public class FilterChain implements Filter{ 8     //用List集合来存储过滤规则 9     List
filters = new ArrayList
();10 //用于标记规则的引用顺序11 int index=0;12 //往规则链条中添加规则13 public FilterChain addFilter(Filter f) {14 filters.add(f);15 //代码的设计技巧:Chain链添加过滤规则结束后返回添加后的Chain,方便我们下面doFilter函数的操作16 return this;17 }18 public void doFilter(Request request,Response response,FilterChain chain){19 //index初始化为0,filters.size()为3,不会执行return操作20 if(index==filters.size()){21 return;22 }23 //每添加一个过滤规则,index自增124 Filter f=filters.get(index);25 index++;26 //根据索引值获取对应的规律规则对字符串进行处理27 f.doFilter(request, response, chain);28 }29 }

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

1 package com.bjsxt.dp.filter; 2  3 /* 4  * 责任链模式: 5  * 数据消息在进入数据库之前,要被多种过滤规则进行处理,多种规则形成一种链,依次处理 6  * 给定的数据消息 7  */ 8 public class Main { 9     public static void main(String args[]) {10         //设定过滤规则,对msg字符串进行过滤处理11         String msg = ":):,

运行结果:

^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信息

运行过程用下图表示:

你可能感兴趣的文章
mysql:sql truncate (清除表数据)
查看>>
scrapy:xpath string(.)非常注意问题
查看>>
yuv to rgb 转换失败呀。天呀。谁来帮帮我呀。
查看>>
yuv420 format
查看>>
单纯的把Y通道提取出来能正确显示出灰度图来为什么我的Qt就显示不出来呢转换有问题呀?
查看>>
YUV420只绘制Y通道
查看>>
yuv420 还原为RGB图像
查看>>
LED恒流驱动芯片
查看>>
驱动TFT要SDRAM做为显示缓存
查看>>
使用file查看可执行文件的平台性,x86 or arm ?
查看>>
qt5 everywhere 编译summary
查看>>
qt5 everywhere编译完成后,找不到qmake
查看>>
arm-linux开机读取硬件时钟,设置系统时钟。
查看>>
交叉编译在x86上调试好的qt程序
查看>>
/dev/input/event0 键盘输入
查看>>
qt 创建异形窗体
查看>>
可重入函数与不可重入函数
查看>>
简单Linux C线程池
查看>>
内存池
查看>>
输入设备节点自动生成
查看>>