抽丝剥茧设计模式- 责任链模式(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()替换字符串的效果是一样,即这两者也支持字符串的操作;
感谢阅读到现在,请在留言区提出宝贵的意见!
更多精彩内容,关注微信公众号:技术严选