责任链设计模式(过滤器/拦截器)
2016-05-27 10:53
344 查看
责任链设计模式(Chain of Responsibility)的应用有:Java Web中的过滤器链、springmvc中的拦截器链,Struts2中的拦截器栈等等。
先看如下一个问题:
给定一个字符串“被就业了:),敏感信息,<script>”,对其中的HTML标记和敏感词进行过滤或替换。本文主要以该问题设计方法的演变来讲解责任链设计模式。
测试结果:
就业了:)
在第一种设计中,对字符串的所有处理都放在MsgProcessor类中,扩展性极差。如果要过滤字符串中的笑脸(将”:)”替换成”^_^”),则需要改动MSgProcessor中的process方法。我们看第二种设计。
2、定义实现几种实现:
3、处理类
4、测试类
测试结果:
就业了:)
此时,如果需要过滤字符串中的笑脸,只需要创建一个类FaceFilter实现Filter接口,并在MsgProcessor类中的filters字段中登记即可。
① 事件处理请求对象(Request)
② 执行对象(Handler)
1、FilterChain
2、SimleFilter
3、MsgFilterChainProcessor
4、MainTest
测试结果:
就业了^_^
上面的实现的过滤链可以用下图a)表示出来,整个过程只对msg过滤了一次。而JavaWeb中的过滤器链和Struts2中的拦截器栈执行的过程可以形象的表示为图b,很重要)。
下面用程序模拟JavaWeb中的过滤器,实现类似于对Request和Response的过滤。主要涉及的类如下所示:
先看如下一个问题:
给定一个字符串“被就业了:),敏感信息,<script>”,对其中的HTML标记和敏感词进行过滤或替换。本文主要以该问题设计方法的演变来讲解责任链设计模式。
第一种设计:没有任何设计模式
设计了一个MsgProcessor类,完成字符串处理的主要工作。MainTest类是本设计中的测试类。package zmx.designmode.test.responsibilitychain; public class MainTest { public static void main(String[] args) { //需要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //实例化处理类 MsgProcessor mp = new MsgProcessor(msg); String r = mp.process(); System.out.println(r); } }
package zmx.designmode.test.responsibilitychain; public class MsgProcessor { private String msg; public MsgProcessor(String msg) { this.msg = msg; } public String process() { String r = msg; // 过滤msg中的HTML标记 r = r.replaceAll("<.*>", ""); // 过滤敏感词 r = r.replace("敏感信息", "").replace("被就业", "就业"); return r; } }
测试结果:
就业了:)
在第一种设计中,对字符串的所有处理都放在MsgProcessor类中,扩展性极差。如果要过滤字符串中的笑脸(将”:)”替换成”^_^”),则需要改动MSgProcessor中的process方法。我们看第二种设计。
第二种设计:增加一个Filter接口
1、filter接口:package zmx.designmode.test.responsibilitychain; public interface Filter { public String doFilter(String str); }
2、定义实现几种实现:
package zmx.designmode.test.responsibilitychain; public class HtmlFilter implements Filter { @Override public String doFilter(String str) { String r = str; //过滤msg中的HTML标记 r = r.replaceAll("<.*>", ""); return r; } }
package zmx.designmode.test.responsibilitychain; public class SensitiveFilter implements Filter { @Override public String doFilter(String str) { String r = str; //过滤str中的敏感信息 r = r.replace("敏感信息", "").replace("被就业", "就业"); return r; } }
3、处理类
package zmx.designmode.test.responsibilitychain; public class MsgFilterProcessor { private String msg; private Filter[] filters= new Filter[]{new HtmlFilter(),new SensitiveFilter()}; public MsgFilterProcessor(String msg) { this.msg = msg; } public String process(){ String r = msg; for(Filter f : filters){ r = f.doFilter(r); } return r; } }
4、测试类
package zmx.designmode.test.responsibilitychain; public class MainTest { public static void main(String[] args) { //需要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //实例化处理类 //MsgProcessor mp = new MsgProcessor(msg); MsgFilterProcessor mp = new MsgFilterProcessor(msg); String r = mp.process(); System.out.println(r); } }
测试结果:
就业了:)
此时,如果需要过滤字符串中的笑脸,只需要创建一个类FaceFilter实现Filter接口,并在MsgProcessor类中的filters字段中登记即可。
第三种设计:责任链模式(FilterChain)
定义:将一个事件处理流程分派到一组执行对象上去,这一组执行对象形成一个链式结构,事件处理请求在这一组执行对象上进行传递。责任链模式的主要参与角色:① 事件处理请求对象(Request)
② 执行对象(Handler)
1、FilterChain
package zmx.designmode.test.responsibilitychain; import java.util.ArrayList; import java.util.List; public class FilterChain implements Filter { public List<Filter> filters = new ArrayList<Filter>(); public FilterChain addFilter(Filter f){ filters.add(f); return this; } @Override public String doFilter(String str) { String r = str; for(Filter f : filters){ r = f.doFilter(r); } return r; } }
2、SimleFilter
package zmx.designmode.test.responsibilitychain; public class SmileFilter implements Filter { @Override public String doFilter(String str) { String r = str; //过滤msg中的笑脸标记 r = r.replace(":)", "^_^"); return r; } }
3、MsgFilterChainProcessor
package zmx.designmode.test.responsibilitychain; public class MsgFilterChainProcessor { private String msg; private FilterChain chain = new FilterChain(); public MsgFilterChainProcessor(String msg, FilterChain filterChain){ this.msg = msg; this.chain = filterChain; } public String process(){ return chain.doFilter(msg); } }
4、MainTest
package zmx.designmode.test.responsibilitychain; public class MainTest { public static void main(String[] args) { //需要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //实例化处理类 //MsgProcessor mp = new MsgProcessor(msg); //MsgFilterProcessor mp = new MsgFilterProcessor(msg); //搞一个过过滤链 FilterChain chain = new FilterChain(); chain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()) .addFilter(new SmileFilter()); //实例化处理类 MsgFilterChainProcessor mp = new MsgFilterChainProcessor(msg,chain); String r = mp.process(); System.out.println(r); } }
测试结果:
就业了^_^
责任链模式加强版
上面的实现的过滤链可以用下图a)表示出来,整个过程只对msg过滤了一次。而JavaWeb中的过滤器链和Struts2中的拦截器栈执行的过程可以形象的表示为图b,很重要)。下面用程序模拟JavaWeb中的过滤器,实现类似于对Request和Response的过滤。主要涉及的类如下所示:
public interface Filter { void doFilter(Request req,Response resp,FilterChain chain); }
public class HtmlFilter implements Filter { public void doFilter(Request req, Response resp, FilterChain chain) { //过滤req.reqStr中的HTML标记 req.reqStr = req.reqStr.replace("<", "<").replace(">", ">"); req.reqStr += "---HtmlFilter()---"; chain.doFilter(req, resp); resp.respStr += "---HtmlFilter()---"; } }
public class SensitiveFilter implements Filter { public void doFilter(Request req, Response resp, FilterChain chain) { // 过滤req.reqStr中的敏感词 req.reqStr = req.reqStr.replace("敏感", "").replace("被就业", "就业"); req.reqStr += "===SensitiveFilter"; chain.doFilter(req, resp); resp.respStr += "===SensitiveFilter"; } }
public class FilterChain{ private List<Filter> filters = new ArrayList<Filter>(); //调用链上的过滤器时,记录过滤器的位置用 private int index = 0; public FilterChain addFilter(Filter f){ filters.add(f); return this; } public void doFilter(Request req, Response resp) { if(index == filters.size()) return; //得到当前过滤器 Filter f = filters.get(index); index++; f.doFilter(req, resp, this); } }
public class Request { //在Request中只保持了一个reqStr字段记录对Request的操作 //为了方便模拟,没有将reqStr设置为private String reqStr; }
public class Response { //在Response中只保持了一个respStr字段记录对Response的操作 //为了方便模拟,没有将respStr设置为private String respStr; }
package org.flyne.fiter; public class MainClass { public static void main(String[] args) { // 需要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //创建Request、Response对象 Request req = new Request(); Response resp = new Response(); req.reqStr = msg; resp.respStr = "response"; //搞一个过滤链,链上有两个过滤器 FilterChain chain = new FilterChain(); chain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); //开始过滤 chain.doFilter(req, resp); System.out.println(req.reqStr); System.out.println(resp.respStr); } }
相关文章推荐
- shell 脚本中常用的列表
- 主成分分析(Principal components analysis)-最大方差解释
- gradle 签名配置
- Pointer
- Android MVC模型解析
- java知识点总结
- SwipeRefreshLayout和RecyclerView整合实现下拉刷新
- Sublime Text3配置备份
- iOS Button 按钮 UIControlStateDisabled 状态的使用
- Androin学习笔记五十五: Android多点触摸交互处理,放大缩小图片
- android MultiDex
- Flume部署和启动
- String自带的replaceAll方法和StringUtils的replaceAll的区别
- Ejabberd作为推送服务的优化手段
- 《解剖PetShop》之四:PetShop之ASP.NET缓存
- 初识安卓基本控件_TimePicker
- 关于闭包的理解
- PHP软件工程师面试题
- [从头学数学] 第225节 返璞归真丹元成
- Hibernate与MyBatis对比