抽丝剥茧设计模式- 责任链模式(Chain of Responsibility Pattern)
一、关于设计模式的思考
1.很多设计模式的区别不是语法的区别,而是语义的区别。
2.最难的是proxy,其次是chain of responsibility,Reactor 也当作设计模式。
3.所谓设计模式 就是把简单问题复杂化,把变化的部分封装那,即"封装变化"。
4.大部分的设计模式都是利用Java多态,多态是Java面向对象的核心。
二、请思考如下需求:
在公众号上发表文章,后台要经过处理才能发表和存如数据库,每个处理策略都要检查一遍。
三、责任链模式(Chain of Responsibility Pattern)
让多个处理请求的对象都有可能接收请求,将这些处理请求的对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
应用场景:servlet Filter、listener
四、例子
package org.design.behavioral.chain;
import java.util.ArrayList;
import java.util.List;
public class ChainOfResponsibility {
public static void main(String[] args) {
Article article = new Article();
article.setArticle("Hello every one,(--)<script> This is a sensitive word! 666");
//java是值传递,函数调用的时候如果是基本类型,传值的copy,如果是引用类型,传的是引用类型地址的copy
//version 1 需要过滤文章中恶意脚本和敏感词
/*
String str = article.getArticle();
//过滤恶意脚本
str = str.replace("<","[");
str = str.replace(">","]");
//过滤敏感词
str = str.replace("sensitive","*");
article.setArticle(str);
System.out.println(article);
*/
//version 2 将过滤策略封装到Filter类中
/*
Filter scriptFilter = new ScriptFilter();
scriptFilter.doFilter(article);
Filter sensitiveFilter = new SensitiveFilter();
sensitiveFilter.doFilter(article);
System.out.println(article);
*/
//version 3 借助list,形成链
/*
List<Filter> filters = new ArrayList<Filter>();
filters.add(new ScriptFilter());
filters.add(new SensitiveFilter());
filters.add(new ExpressionFilter());
filters.add(new NumberFilter());
for(Filter f:filters){
f.doFilter(article);
}
System.out.println(article);
*/
//version 4 filter chain,与version相比,只不过把add 和遍历方法放到FilterChainV1中了。
//编程小技巧:将Filter们构成链条,链式编程。
/*
FilterChainV1 chainV1 = new FilterChainV1();
chainV1.add(new ScriptFilter()).add(new NumberFilter());
chainV1.doFilter(article);
System.out.println(article);
FilterChainV1 chainV2 = new FilterChainV1();
chainV2.add(new ExpressionFilter()).add(new SensitiveFilter());
chainV2.doFilter(article);
System.out.println(article);
*/
/*
version 5 FilterChain其实自己也是一个Filter,像递归。
FilterChainV2 implements Filter
FilterChainV2 chainV21 = new FilterChainV2();
chainV21.add(new ScriptFilter()).add(new NumberFilter());
FilterChainV2 chainV22 = new FilterChainV2();
chainV22.add(new ExpressionFilter()).add(new SensitiveFilter());
chainV21.add(chainV22);
chainV21.doFilter(article);
System.out.println(article);
*/
/*
version 6 由FilterChain中的某一个Filter决定链条是否继续。Filter中增加返回值,继续返回true,终止返回false。
判断逻辑放在FilterChain中不合适,由Filter自己决定是否继续更合理。
因为扩展Filter的时候,应该由扩展的Filter决定是否继续,不用修改FilterChain。
*/
FilterChin chain = new FilterChin();
chain.add(new ScriptFilter()).add(new NumberFilter()).add(new ExpressionFilter()).add(new SensitiveFilter());
chain.doFilter(article);
System.out.println(article);
}
}
class Article {
public String article;
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
}
@Override
public String toString() {
return "Article{" +
"article='" + article + '\'' +
'}';
}
}
interface Filter {
boolean doFilter(Article article);
}
class ScriptFilter implements Filter {
@Override
public boolean doFilter(Article article) {
System.out.println("Exec ScriptFilter");
//过滤恶意脚本
String str = article.getArticle();
str = str.replace("<", "[");
str = str.replace(">", "]");
article.setArticle(str);
return true;
}
}
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Article article) {
System.out.println("Exec SensitiveFilter");
//过滤敏感词
String str = article.getArticle();
str = str.replace("sensitive", "*");
article.setArticle(str);
return false;
}
}
class ExpressionFilter implements Filter {
@Override
public boolean doFilter(Article article) {
System.out.println("Exec ExpressionFilter");
//过滤表情
String str = article.getArticle();
str = str.replace("(--)", "@");
article.setArticle(str);
return true;
}
}
class NumberFilter implements Filter {
@Override
public boolean doFilter(Article article) {
System.out.println("Exec NumberFilter");
//过滤数字
String str = article.getArticle();
str = str.replaceAll("\\d", "000");
article.setArticle(str);
return true;
}
}
class FilterChainV1 {
List<Filter> filters = new ArrayList<Filter>();
////编程小技巧:return FilterChain,将FilterChain形成链 类似StringBuffer.append();
public FilterChainV1 add(Filter filter) {
this.filters.add(filter);
return this;
}
public void doFilter(Article article) {
for (Filter f : filters) {
f.doFilter(article);
}
}
}
class FilterChainV2 implements Filter {
List<Filter> filters = new ArrayList<Filter>();
////编程小技巧:return FilterChain,将FilterChain形成链 类似StringBuffer.append();
public FilterChainV2 add(Filter filter) {
this.filters.add(filter);
return this;
}
public boolean doFilter(Article article) {
for (Filter f : filters) {
f.doFilter(article);
}
return true;
}
}
class FilterChin implements Filter {
List<Filter> filters = new ArrayList<Filter>();
FilterChin add(Filter filter) {
this.filters.add(filter);
return this;
}
@Override
public boolean doFilter(Article article) {
for (Filter f : filters) {
if (!f.doFilter(article)) ;
return false;
}
return true;
}
}
五、补充知识:
1.replace的参数是char和CharSequence,既可以支持字符的替换,也支持字符串的替换(CharSequence字符串序列);
2.replaceAll的参数是regex或者char,基于正则表达式的替换,例如通过replaceAll("\\d", "#")把一个字符串所有的数字字符都换成#号;
3.相同点:均为全部替换,把源字符串中的某一字符或字符串全部换成指定的字符或字符串。
4.如果只想替换第一次出现的,使用replaceFirst(),改方法也是基于正则表达式的替换,与replaceAll()不同的时,仅替换第一次出现的字符串;
5.如果replaceAll()和replaceFirst()所用的参数据不是基于正则表达式,则与replace()替换字符串的效果是一样,即这两者也支持字符串的操作;
感谢阅读到现在,请在留言区提出宝贵的意见!
更多精彩内容,关注微信公众号:技术严选


浙公网安备 33010602011771号