参考于 :
大话设计模式
马士兵设计模式视频
代码参考于马士兵设计模式视频
写在开头:职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系
图来自大话设计模式,下面我的代码中,Clien是t依赖于Handler1和Handler2的,不过可以使用配置文件或者直接给Filter集合初始化来解决这种依赖。
1.场景
在网上评论一句话,往往会经过一系列的处理,有没有敏感词之类,现在我们来模拟一下。
把<html>,o.o,和谐
换成 [html],^v^,/*河蟹*/
2.不使用职责链模式
package com.dingyu.ChainOfResponsibility; /** * 重点在于模式,故逻辑暂时不考虑 * * @author dingyu * */ public class Client01 { public static void main(String[] args) { String s = "<html>,o.o,和谐"; s = s.replace("<", "[").replace(">", "]").replace("和谐", "/*河蟹*/").replace("o.o", "^v^"); System.out.println(s); } }
缺点:过滤无法复用,无法记录过滤顺序。
3.使用职责链模式
package com.dingyu.ChainOfResponsibility; /** * 过滤器,doFilter处理msg字符串 * @author dingyu * */ public interface Filter { public String doFilter(String msg); }
package com.dingyu.ChainOfResponsibility; /** * 处理html符号 * 测试用的,逻辑不是很严谨 * @author dingyu * */ public class HTMLFilter implements Filter { @Override public String doFilter(String msg) { return msg.replace("<", "[").replace(">", "]"); } }
package com.dingyu.ChainOfResponsibility; /** * 过滤敏感词汇 * @author dingyu * */ public class SensitiveWordFilter implements Filter { @Override public String doFilter(String msg) { return msg.replace("和谐", "/*河蟹*/"); } }
package com.dingyu.ChainOfResponsibility; /** * 处理符号 * @author dingyu * */ public class SymbolFilter implements Filter { @Override public String doFilter(String msg) { return msg.replace("o.o", "^v^"); } }
package com.dingyu.ChainOfResponsibility; import java.util.ArrayList; import java.util.List; public class Client { private static List<Filter> filters = new ArrayList<Filter>(); private static int index = 0; public static void main(String[] args) { String s = "<html>,o.o,和谐"; filters.add(new HTMLFilter()); filters.add(new SymbolFilter()); filters.add(new SensitiveWordFilter()); for (Filter filter : filters) { s = filter.doFilter(s); } System.out.println(s); } }
虽然使用职责链模式,但仍然有缺点,上面的顺序是先HTML,然后Symbol,最后SensitiveWord,这三个构成一个过滤链条,如果有一天我需要把另一个过滤链条插入到这根链条中间,实现起来很麻烦。
4.改进职责链模式
package com.dingyu.ChainOfResponsibility; import java.util.ArrayList; import java.util.List; /** * * @author dingyu * */ public class FilterChain implements Filter { private List<Filter> filters = new ArrayList<Filter>(); public void add(Filter filter) { filters.add(filter); } public List<Filter> getFilters() { return filters; } @Override public String doFilter(String msg) { for (Filter filter : filters) { msg = filter.doFilter(msg); } return msg; } }
package com.dingyu.ChainOfResponsibility; import java.util.ArrayList; import java.util.List; public class Client { // private static List<Filter> filters = new ArrayList<Filter>(); public static void main(String[] args) { String s = "<html>,o.o,和谐"; // 链条1 FilterChain chain1 = new FilterChain(); chain1.add(new HTMLFilter()); // 链条2 FilterChain chain2 = new FilterChain(); chain2.add(new HTMLFilter()); chain2.add(new SensitiveWordFilter()); // 链条2插到链条1后 chain1.add(chain2); chain1.add(new SymbolFilter()); s = chain1.doFilter(s); System.out.println(s); // filters.add(new HTMLFilter()); // filters.add(new SymbolFilter()); // filters.add(new SensitiveWordFilter()); // for (Filter filter : filters) { // s = filter.doFilter(s); // } // System.out.println(s); } }
建议debug , eclipse快捷键
5. 职责链实现双向过滤
思路类似于递归,建议使用debug一步步调试。
package com.dingyu.ChainOfResponsibility; /** * 过滤器,doFilter处理msg字符串 * * @author dingyu * */ public interface Filter { // public String doFilter(String msg); public void doFilter(Request request, Reponse reponse, FilterChain filterChain); }
package com.dingyu.ChainOfResponsibility; /** * 处理html符号 测试用的,逻辑不是很严谨 * * @author dingyu * */ public class HTMLFilter implements Filter { @Override public void doFilter(Request request, Reponse reponse, FilterChain filterChain) { request.getRequestMsg().replace("<", "[").replace(">", "]"); filterChain.doFilter(request, reponse, filterChain); reponse.setReponseMsg(reponse.getReponseMsg() + "-----HTMLFilter"); } // @Override // public String doFilter(String msg) { // return msg.replace("<", "[").replace(">", "]"); // } }
package com.dingyu.ChainOfResponsibility; /** * 过滤敏感词汇 * * @author dingyu * */ public class SensitiveWordFilter implements Filter { @Override public void doFilter(Request request, Reponse reponse, FilterChain filterChain) { request.getRequestMsg().replace("和谐", "/*河蟹*/"); filterChain.doFilter(request, reponse, filterChain); reponse.setReponseMsg(reponse.getReponseMsg() + "-----SensitiveWordFilter"); } // @Override // public String doFilter(String msg) { // return msg.replace("和谐", "/*河蟹*/"); // } }
package com.dingyu.ChainOfResponsibility; /** * 处理符号 * * @author dingyu * */ public class SymbolFilter implements Filter { @Override public void doFilter(Request request, Reponse reponse, FilterChain filterChain) { request.getRequestMsg().replace("o.o", "^v^"); filterChain.doFilter(request, reponse, filterChain); reponse.setReponseMsg(reponse.getReponseMsg() + "-----SymbolFilter"); } // @Override // public String doFilter(String msg) { // return msg.replace("o.o", "^v^"); // } }
package com.dingyu.ChainOfResponsibility; import java.util.ArrayList; import java.util.List; /** * * @author dingyu * */ public class FilterChain implements Filter { private List<Filter> filters = new ArrayList<Filter>(); private int index=-1; public void add(Filter filter) { filters.add(filter); } public List<Filter> getFilters() { return filters; } // @Override // public String doFilter(String msg) { // for (Filter filter : filters) { // msg = filter.doFilter(msg); // } // return msg; // } @Override public void doFilter(Request request, Reponse reponse, FilterChain filterChain) { if (index == filters.size()-1) return; index++; filters.get(index).doFilter(request, reponse, filterChain); } }
package com.dingyu.ChainOfResponsibility; public class Client03 { public static void main(String[] args) { Request request = new Request(); Reponse reponse = new Reponse(); request.setRequestMsg("<html>,o.o,和谐"); reponse.setReponseMsg("hahahahaha"); FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()); chain.add(new SensitiveWordFilter()); chain.add(new SymbolFilter()); chain.doFilter(request, reponse, chain); System.out.println(request.getRequestMsg()); System.out.println(reponse.getReponseMsg()); } }