大话设计模式之—责任链模式
- 2019 年 12 月 16 日
- 筆記
责任链模式,又称职责链模式,Chain Of Responsibility,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
根据代码来体验,模仿前端消息传递过滤。
package com.kk; /** * @author zhaokk * @create 2019-12-08-10:06 */ public class ChainOfResponsibility { public static void main(String[] args) { Msg msg = new Msg(); //消息接收 msg.setMsg("你好:),<script>,欢迎的来到996icu"); String str=msg.getMsg(); str = str.replace('<', '['); str= str.replace('>',']'); msg.setMsg(str); str= str.replaceAll("996icu","955happy"); msg.setMsg(str); //过滤 System.out.println(msg.getMsg()); } } class Msg { String name; String msg; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } @Override public String toString() { return "Msg{" + "name='" + name + ''' + ", msg='" + msg + ''' + '}'; } }
输出:
D:ProgramFilesJavaTestjavajdk1.8.0_141binjava.exe "-javaagent:D:ideaIntelliJ IDEA 2019.1.1libidea_rt.jar=51670:D:ideaIntelliJ IDEA 2019.1.1bin" -Dfile.encoding=UTF-8 -classpath D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibcharsets.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibdeploy.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextaccess-bridge-64.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextcldrdata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextdnsns.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjaccess.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjfxrt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextlocaledata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextnashorn.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunec.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunjce_provider.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunmscapi.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunpkcs11.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextzipfs.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjavaws.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjce.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfr.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfxswt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjsse.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibmanagement-agent.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibplugin.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibresources.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibrt.jar;D:project01targetclasses;C:Users14620.m2repositorycommons-loggingcommons-logging1.1.3commons-logging-1.1.3.jar;C:Users14620.m2repositorylog4jlog4j1.2.17log4j-1.2.17.jar;C:Users14620.m2repositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:Users14620.m2repositoryorgslf4jslf4j-log4j121.7.7slf4j-log4j12-1.7.7.jar;C:Users14620.m2repositorychqoslogbacklogback-classic1.1.7logback-classic-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-core1.1.7logback-core-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-access1.1.7logback-access-1.1.7.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-core2.5log4j-core-2.5.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-api2.5log4j-api-2.5.jar;C:Users14620.m2repositoryjunitjunit4.12junit-4.12.jar;C:Users14620.m2repositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar com.kk.ChainOfResponsibility 你好:),[script],欢迎的来到955happy Process finished with exit code 0
这里的消息指request请求获取缓存中消息,或者用户输入消息,当进行消息过滤时,添加一个特殊符号过滤,添加一个敏感词过滤处理消息。但当增加需求或者改变敏感词时,需要增加新功能,且耦合较高。
将变化的代码逻辑封装变化
处理信息的部分是变化的
我们定义一个接口为Filter
package com.kk; /** * @author zhaokk * @create 2019-12-08-10:24 */ public interface Filter { void dofilter(Msg msg); }
处理信息的两个实现类
package com.kk; /** * 特殊符号 * @author zhaokk * @create 2019-12-08-10:26 */ public class SpecialFilter implements Filter{ public void dofilter(Msg msg) { String str=msg.getMsg(); str = str.replace('<', '['); str= str.replace('>',']'); msg.setMsg(str); } }
package com.kk; /** * 敏感词 * @author zhaokk * @create 2019-12-08-10:27 */ public class SensitiveFilter implements Filter { public void dofilter(Msg msg) { String str=msg.getMsg(); str= str.replaceAll("996icu","955happy"); msg.setMsg(str); } }
public class ChainOfResponsibility { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("你好:),<script>,欢迎的来到996icu"); new SpecialFilter().dofilter(msg); new SensitiveFilter().dofilter(msg); /* String str=msg.getMsg(); str = str.replace('<', '['); str= str.replace('>',']'); msg.setMsg(str); str= str.replaceAll("996icu","955happy"); msg.setMsg(str);*/ System.out.println(msg.getMsg()); } }
输出:
D:ProgramFilesJavaTestjavajdk1.8.0_141binjava.exe "-javaagent:D:ideaIntelliJ IDEA 2019.1.1libidea_rt.jar=52130:D:ideaIntelliJ IDEA 2019.1.1bin" -Dfile.encoding=UTF-8 -classpath D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibcharsets.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibdeploy.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextaccess-bridge-64.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextcldrdata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextdnsns.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjaccess.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjfxrt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextlocaledata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextnashorn.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunec.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunjce_provider.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunmscapi.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunpkcs11.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextzipfs.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjavaws.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjce.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfr.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfxswt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjsse.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibmanagement-agent.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibplugin.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibresources.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibrt.jar;D:project01targetclasses;C:Users14620.m2repositorycommons-loggingcommons-logging1.1.3commons-logging-1.1.3.jar;C:Users14620.m2repositorylog4jlog4j1.2.17log4j-1.2.17.jar;C:Users14620.m2repositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:Users14620.m2repositoryorgslf4jslf4j-log4j121.7.7slf4j-log4j12-1.7.7.jar;C:Users14620.m2repositorychqoslogbacklogback-classic1.1.7logback-classic-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-core1.1.7logback-core-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-access1.1.7logback-access-1.1.7.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-core2.5log4j-core-2.5.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-api2.5log4j-api-2.5.jar;C:Users14620.m2repositoryjunitjunit4.12junit-4.12.jar;C:Users14620.m2repositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar com.kk.ChainOfResponsibility 你好:),[script],欢迎的来到955happySun Dec 08 10:32:19 CST 2019 Process finished with exit code 0
但是此时如果新的业务逻辑进入还需要定义并引入Filter,如果将所有的Filter放入List,foreachList,也可以将多个Filter穿起来,但是新的Filter增加特需要add。且循环过程中,需要所有Filter过滤完才放出.定义一个
FilterChain
ackage com.kk; import java.util.ArrayList; import java.util.List; /** * @author zhaokk * @create 2019-12-08-10:40 */ public class FilterChain { List<Filter> filterList=new ArrayList<Filter>(); private Msg msg; public void add(Filter filter){ filterList.add(filter); } public void doFilter(Msg msg){ for (Filter filter : filterList) { filter.dofilter(msg); } } }
处理逻辑
public class ChainOfResponsibility { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("你好:),<script>,欢迎的来到996icu"); FilterChain fc = new FilterChain(); fc.add(new SpecialFilter()); fc.add(new SensitiveFilter()); fc.doFilter(msg); /* String str=msg.getMsg(); str = str.replace('<', '['); str= str.replace('>',']'); msg.setMsg(str); str= str.replaceAll("996icu","955happy"); msg.setMsg(str);*/ System.out.println(msg.getMsg()+new Date()); } }
输出:
D:ProgramFilesJavaTestjavajdk1.8.0_141binjava.exe "-javaagent:D:ideaIntelliJ IDEA 2019.1.1libidea_rt.jar=52490:D:ideaIntelliJ IDEA 2019.1.1bin" -Dfile.encoding=UTF-8 -classpath D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibcharsets.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibdeploy.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextaccess-bridge-64.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextcldrdata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextdnsns.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjaccess.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjfxrt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextlocaledata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextnashorn.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunec.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunjce_provider.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunmscapi.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunpkcs11.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextzipfs.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjavaws.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjce.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfr.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfxswt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjsse.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibmanagement-agent.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibplugin.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibresources.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibrt.jar;D:project01targetclasses;C:Users14620.m2repositorycommons-loggingcommons-logging1.1.3commons-logging-1.1.3.jar;C:Users14620.m2repositorylog4jlog4j1.2.17log4j-1.2.17.jar;C:Users14620.m2repositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:Users14620.m2repositoryorgslf4jslf4j-log4j121.7.7slf4j-log4j12-1.7.7.jar;C:Users14620.m2repositorychqoslogbacklogback-classic1.1.7logback-classic-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-core1.1.7logback-core-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-access1.1.7logback-access-1.1.7.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-core2.5log4j-core-2.5.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-api2.5log4j-api-2.5.jar;C:Users14620.m2repositoryjunitjunit4.12junit-4.12.jar;C:Users14620.m2repositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar com.kk.ChainOfResponsibility 你好:),[script],欢迎的来到955happySun Dec 08 10:53:22 CST 2019 Process finished with exit code 0
此时我们再增加一个对消息处理的RedisFilter,
package com.kk; /** * @author zhaokk * @create 2019-12-08-10:58 */ public class RedisFilter implements Filter { public void doFilter(Msg msg) { String rediskry="TH"+msg; rediskry.replace(":)",""); msg.setMsg(rediskry); } }
然后让FilterChain也实现Filter接口
public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("你好:),<script>,欢迎的来到996icu"); FilterChain fc = new FilterChain(); fc.add(new SpecialFilter()) .add(new SensitiveFilter()); FilterChain fc2 = new FilterChain(); fc2.add(new RedisFilter()); fc2.doFilter(msg); fc.doFilter(msg); //fc.add(new SensitiveFilter()); /* String str=msg.getMsg(); str = str.replace('<', '['); str= str.replace('>',']'); msg.setMsg(str); str= str.replaceAll("996icu","955happy"); msg.setMsg(str);*/ System.out.println(msg.getMsg()+new Date()); }
但是这里的消息,必须一条责任链处理完,另一条责任链也要处理
将一个链条看做是Filter加到FilterChain链中
fc.add(fc2);
在某一个filter中决定是否继续往下处理
将Filter返回boolean
public interface Filter { Boolean doFilter(Msg msg); }
其他三个过滤器除敏感词返回false外返回true
public class SensitiveFilter implements Filter { public Boolean doFilter(Msg msg) { String str=msg.getMsg(); str= str.replaceAll("996icu","955happy"); msg.setMsg(str); return false; } }
在filterChain中
public Boolean doFilter(Msg msg) { for (Filter filter : filterList) { if (!filter.doFilter(msg)) { return false; } } return true; }
此时在三个责任链中第二个是返回false,第三个是不予执行的,RedisFilter效果不被执行
D:ProgramFilesJavaTestjavajdk1.8.0_141binjava.exe "-javaagent:D:ideaIntelliJ IDEA 2019.1.1libidea_rt.jar=52994:D:ideaIntelliJ IDEA 2019.1.1bin" -Dfile.encoding=UTF-8 -classpath D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibcharsets.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibdeploy.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextaccess-bridge-64.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextcldrdata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextdnsns.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjaccess.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextjfxrt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextlocaledata.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextnashorn.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunec.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunjce_provider.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunmscapi.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextsunpkcs11.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibextzipfs.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjavaws.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjce.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfr.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjfxswt.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibjsse.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibmanagement-agent.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibplugin.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibresources.jar;D:ProgramFilesJavaTestjavajdk1.8.0_141jrelibrt.jar;D:project01targetclasses;C:Users14620.m2repositorycommons-loggingcommons-logging1.1.3commons-logging-1.1.3.jar;C:Users14620.m2repositorylog4jlog4j1.2.17log4j-1.2.17.jar;C:Users14620.m2repositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:Users14620.m2repositoryorgslf4jslf4j-log4j121.7.7slf4j-log4j12-1.7.7.jar;C:Users14620.m2repositorychqoslogbacklogback-classic1.1.7logback-classic-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-core1.1.7logback-core-1.1.7.jar;C:Users14620.m2repositorychqoslogbacklogback-access1.1.7logback-access-1.1.7.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-core2.5log4j-core-2.5.jar;C:Users14620.m2repositoryorgapachelogginglog4jlog4j-api2.5log4j-api-2.5.jar;C:Users14620.m2repositoryjunitjunit4.12junit-4.12.jar;C:Users14620.m2repositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar com.kk.ChainOfResponsibility 你好:),[script],欢迎的来到955happySun Dec 08 11:22:49 CST 2019 Process finished with exit code 0
模拟Severlet API Filter

如何在一条责任链处理request与response

response向上返回处理结果
当Filter处理request的时候,让当前的Filter找到下一个Filter,下一个Filter如此,直到处理完再处理response然后向上返回response至第一层
package com.kk; /** * @author zhaokk * @create 2019-12-08-10:24 */ public interface Filter { Boolean doFilter(Request request, Response response,FilterChain filterChain); }
接受者和发送者都没有对方的明确消息,且链中的对象结构也不知道链的结构,职责链可以简化对象的相互连接,且易于扩展
package com.kk; /** * @author zhaokk * @create 2019-12-08-10:26 */ public class SpecialFilter implements Filter { public void doFilter(Request request, Response response, FilterChain filterChain) { request.setStr(request.getStr().replace('<', '[').replace(">", "]") + "---SpecialFilter()"); filterChain.doFilter(request, response, filterChain); response.setStr(response.getStr() + "---SpecialFilter()"); } }
package com.kk; /** * @author zhaokk * @create 2019-12-08-10:58 */ public class RedisFilter implements Filter { public void doFilter(Request request, Response response,FilterChain filterChain) { String rediskry="TH"+request.getStr(); request.setStr(rediskry.replace(":)","") + "---SpecialFilter()"); filterChain.doFilter(request, response, filterChain); } }
FilterChain
package com.kk; import java.util.ArrayList; import java.util.List; /** * @author zhaokk * @create 2019-12-08-10:40 */public class FilterChain implements Filter { List<Filter> filterList = new ArrayList<Filter>(); private Msg msg; public FilterChain add(Filter filter) { filterList.add(filter); return this; } public void doFilter(Request request, Response response,FilterChain filterChain) { filterChain.doFilter(request,response,filterChain); }}
package com.kk; import java.util.ArrayList; import java.util.List; /** * @author zhaokk * @create 2019-12-08-10:40 */public class FilterChain implements Filter { List<Filter> filterList = new ArrayList<Filter>(); private Msg msg; public FilterChain add(Filter filter) { filterList.add(filter); return this; } public void doFilter(Request request, Response response,FilterChain filterChain) { filterChain.doFilter(request,response,filterChain); }}
关于设计模式有23种之多,平时看过,只是并不能强化记忆,除了自己做的demo外,很少能第二次用于平时项目,针对性学习,更能加强记忆
为什么平时看资料会累,因为
第一漫无目的
第二看完得不到应用
第三根本不感兴趣
所以有些书,有些视频资料,看一段时间就坚持不下去了
单纯通过公众号学习一门技术是不现实的,只是记录下当下关注的技术点,并不能够达到教学的级别,个人也比较随意,对有些人有帮助,他就觉得你不错,对别人来说没帮助,那就很水,但我的目的不在这,我只是享受多年后回来看的那种成就感
平时一有什么想法我会及时记录到随笔中,并以此为乐趣,有时我们难于表达,这些随笔能记录并激发你的表达能力