责任链(ChainOfResponsibility)
对于设计模式的学习,必定要动手,并且要屡次练习,而后慢慢消化和理解,才能明白其精髓。可是,设计模式只是在特殊情景下的特殊解决方案,不要滥用,不要为了使用设计模式而硬生生得去使用。设计模式的使用应该天然、优雅!java
问题
1 |
public class TestMain { |
2 |
public static void main(String[] args) { |
3 |
String str = "你好:),这句话中有敏感词汇,须要处理。<script>,敏感!" ; |
4 |
MsgProcessor pro = new MsgProcessor(); |
6 |
str = pro.processor();--- |
7 |
System.out.println(str); |
另外一个类:web
01 |
public class MsgProcessor { |
03 |
public String getMsg() { |
06 |
public void setMsg(String msg) { |
10 |
public String processor(){ |
12 |
if ( null != msg && !( "" ).equals(msg.trim())){ |
13 |
content = msg.replace( "<" , "{" ) |
16 |
content = content.replace( "敏感" , "" ); |
17 |
content = content.replace( ":)" , "^V^" ); |
上面的代码完成了对一个字符串的简单过滤,可是很明显这样的代码很很差。扩展性很差,写得也不够好。这样之后须要添加别的过滤功能不是很方便,老是要修改这个类,一点都不灵活,想把对字符串的过滤行为抽象出来,由于这部分是变化的,天然而然想到使用接口。编程

代码修改成:设计模式
1 |
public String processor(){ |
2 |
if ( null != msg && !( "" ).equals(msg.trim())){ |
3 |
msg = new HTMLFilter().doFilter(msg); |
4 |
msg = new SmileFilter().doFilter(msg); |
5 |
msg = new SensitivityFilter().doFilter(msg); |
这样仍是不够灵活,直接在 MsgProcessor 类中添加一个数组来保存过滤器,而后在 processor** 方法中进行屡次调用:数组
修改成:数据结构
1 |
public String processor(){ |
2 |
if ( null != msg && !( "" ).equals(msg.trim())){ |
3 |
for (Filter f : filters){ |
这样调整后,全部的过滤器都起做用了,添加起来更加灵活一些,而且过滤器的执行顺序也是可控的。ide
当多个过滤器组合在一块儿,就造成了过滤器链,到这里,责任链有点雏形了。学习
新的问题
若是原本已经存在一个过滤器链条了,我想把一些新的过滤器链加进去,而且加入的顺序能够随意控制(随意组合任意的过滤器链条),该怎么办呢?this
定义一个过滤器链类,这这个类中定义添加过滤器的方法,以及运行整个链条上的全部过滤器的方法,而且返回结果。url
代码修改成:
MsgProcessor.java :
01 |
public class MsgProcessor { |
04 |
private FilterChain fc; |
06 |
public FilterChain getFc() { |
09 |
public void setFc(FilterChain fc) { |
12 |
public String getMsg() { |
15 |
public void setMsg(String msg) { |
19 |
public String processor(){ |
20 |
return fc.doFilter(msg); |
FilterChain.java:
01 |
public class FilterChain { |
02 |
List<Filter> filters = new ArrayList<Filter>(); |
04 |
public FilterChain addFilter(Filter filter){ |
09 |
public String doFilter(String str){ |
10 |
if ( null != str && !( "" ).equals(str.trim())){ |
11 |
for (Filter f : filters){ |
12 |
str = f.doFilter(str); |
TestMain.java
01 |
public class TestMain { |
02 |
public static void main(String[] args) { |
03 |
String str = "你好:),这句话中有敏感词汇,须要处理。<script>,敏感!" ; |
04 |
MsgProcessor mp = new MsgProcessor(); |
06 |
FilterChain fc = new FilterChain(); |
07 |
fc.addFilter( new HTMLFilter()) |
08 |
.addFilter( new SmileFilter()) |
09 |
.addFilter( new SensitivityFilter()); |
12 |
System.out.println(str); |
写到这里,仍是没有解决咱们的问题,怎样灵活合并过滤器链呢? 很简单,咱们能够将过滤器链这个类,看成一个很大的过滤器来处理,这样就能够了。让 FilterChain 也实现Filter接口,这样就解决了这个问题!完成这一步,就已经有了责任链模式的味道了!
思考实际开发中的问题
在实际开发中,咱们见过的过滤器都能进行双向的处理,也就是说,能处理request和response,并且是先挨着处理request,而后再反向处理response,这又是怎么实现的呢?

定义一个Request和Response,在实际的web容器中,容器会帮助咱们生成这两个对象,并且在其中封装了不少的东西,在这里,只是模拟,只需简单定义就能够了。
Request.java
2 |
private String requestStr; |
3 |
public String getRequestStr() { |
6 |
public void setRequestStr(String requestStr) { |
7 |
this .requestStr = requestStr; |
Response.java
1 |
public class Response { |
2 |
private String responseStr; |
3 |
public String getResponseStr() { |
6 |
public void setResponseStr(String responseStr) { |
7 |
this .responseStr = responseStr; |
定义好这两个类以后,修改以前的程序:
Filter.java
1 |
public interface Filter { |
2 |
public abstract void doFilter(Request request, Response response); |
别的代码跟着这个接口一块儿改就能够了,可是你会发现,仍是不能实现咱们想要的效果,这个时候须要一些编程的手法,咱们继续修改Filter接口:
Filter.java
1 |
public interface Filter { |
2 |
public abstract void doFilter(Request request, Response response, FilterChain filterChain); |
为何要这样修改,由于只有这样才能把链条握在每个过滤器手中,有了链条,就能够控制链条了:
FilterChain.java
01 |
public class FilterChain implements Filter { |
02 |
private List<Filter> filters = new ArrayList<Filter>(); |
03 |
private int index = 0 ; |
04 |
public FilterChain addFilter(Filter filter){ |
05 |
this .filters.add(filter); |
09 |
public void doFilter(Request request, Response response, |
10 |
FilterChain filterChain) { |
11 |
if (index >= filters.size()) return ; |
12 |
Filter f = filters.get(index); |
14 |
f.doFilter(request, response, filterChain); |
HTMLFilter.java
01 |
public class HTMLFilter implements Filter { |
03 |
public void doFilter(Request request, Response response, |
04 |
FilterChain filterChain) { |
05 |
String str = request.getRequestStr(); |
06 |
System.out.println(str); |
07 |
filterChain.doFilter(request, response, filterChain); |
08 |
String resStr = response.getResponseStr(); |
09 |
System.out.println(resStr); |
如今来看,每一个过滤器都持有过滤器链,在处理完request后,调用下一个过滤器,因为方法是栈结构,这样就会造成一个过滤器栈,拥有栈的数据结构特色。这也是为何Struts在配置多个拦截器的时候,成为拦截器栈的缘由。 因为栈的数据特色,就能达到咱们想要的特色,按照过滤器的次序,依次处理完request,而后再反向依次处理response。这就是责任链模式在实际开发中的使用。