一、背景介绍
工作之余对于用到的设计模式进行总结再梳理,发现职责链模式的妙处以及五大原则的指导下更能发挥职责链模式的优势于是乎便有了这篇博文的诞生
阅读这篇文章会让小编陪着您一起游历职责链模式,以及体会职责链在五大原则的指导下更大作用的发挥;过程中还会涉及小编的学习过程中的思路、总结以及产生的问题,希望能够和您碰撞出更多的"车祸"。
二、学习思路
1.绘制模式的UML图
2.根据UML图编写代码
3.寻找模式的场景例子进行UML图的绘制
4.根据场景例子的UML图编写代码
5.职责链和五大原则的指导思考
三、学习过程
3.1.概念:
职责链模式(Chain of Responsibility): 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
3.2.模式uml图
3.3.模式uml图对应代码
/** * 功能描述:客户端 * * @Author:makang * @Date: 2021/5/27 10:02 */ public class Client { public static void main(String[] args) { //实例化节点1 Handler handler = new ConcreteHandler1(); //实例化节点2 Handler handler1 = new ConcreteHandler2(); //构建链 handler.setSuccessor(handler1); //进行调用 handler.HandleRequest(20); } }
/** * 功能描述:链中节点的抽象类 * * @Author:makang * @Date: 2021/5/26 18:00 */ public abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); }
/** * 功能描述:节点1 * * @Author:makang * @Date: 2021/5/27 9:57 */ public class ConcreteHandler1 extends Handler{ @Override public void HandleRequest(int request) { if(request >=0 && request < 10){ System.out.println("在0-10范围 审批通过"); }else{ if(successor != null){ successor.HandleRequest(request); System.out.println("请求是否会返回============="); }else { System.out.println("已经走到了职责链的最后!!!"); } } } }
/** * 功能描述:节点2 * * @Author:makang * @Date: 2021/5/27 10:00 */ public class ConcreteHandler2 extends Handler{ @Override public void HandleRequest(int request) { if(request >=10 && request < 50){ System.out.println("申请在10-50之间审批通过"); }else{ successor.HandleRequest(request); } } }
3.4.filter拦截器对应的职责链需求
需要实现将请求中的HTML过滤和字符串替换,将最终结果返回
3.5.filter拦截器对应的职责链uml图
3.6.filter拦截器对应的职责链代码
import java.util.ArrayList; import java.util.List; public class ServletMain { public static void main(String[] args) { Request request = new Request(); request.str = "大家好,我是~~;<script>,很高兴能够和大家沟通交流;我们都是007"; Response response = new Response(); response.str = "response返回参数"; //实例化过滤链对象 FilterChain chain = new FilterChain(); //给过滤链对象添加过滤对象 chain.add(new HTMLFilter()).add(new SensitiveFilter()); //执行过滤方法 chain.doFilter(request,response,chain); System.out.println(request.str); System.out.println(response.str); } } /** * filter接口 */ interface Filter{ boolean doFilter(Request request,Response response,FilterChain filterChain); } /** * html过滤filter实现 */ class HTMLFilter implements Filter{ @Override public boolean doFilter(Request request, Response response, FilterChain filterChain) { request.str = request.str.replace("<","[").replace(">","]")+"--HTMLFilter"; filterChain.doFilter(request,response,filterChain); response.str = response.str+"--HTMLFilter"; return true; } } /** * 请求类 */ class Request{ String str; } /** * 响应类 */ class Response{ String str; } /** * 字符串替换filter实现类 */ class SensitiveFilter implements Filter{ @Override public boolean doFilter(Request request, Response response, FilterChain filterChain) { request.str = request.str.replace("007","0071")+"--SensitiveFilter"; filterChain.doFilter(request,response,filterChain); response.str = response.str+"--SensitiveFilter"; return true; } } /** *过滤链类 */ class FilterChain implements Filter{ //存放过滤对象集合 List<Filter> filters = new ArrayList<>(); int index = 0; //添加过滤对象方法 public FilterChain add(Filter filter) { filters.add(filter); return this; } //实现根据过滤对象集合顺序进行过滤操作 @Override public boolean doFilter(Request request, Response response, FilterChain filterChain) { if(index == filters.size()){ return false; } Filter f = filters.get(index); index ++; return f.doFilter(request,response,filterChain); } }
注:filter自定义拦截器可以通过@Order()注解来设置先后顺序
3.7.扩展
需求
1.如何做到增加链中节点,符合开闭原则?
2.如何做到修改链中节点先后顺序,符合开闭原则?
方案:
1.非spring管理的项目:将链中的下一个节点的包路径放到配置文件中,调用过程中通过读取配置文件的包路径采用反射来获得下一个节点的对象
2.spring管理的项目:将链中的下一个节点的beanName放到配置文件中,调用过程中通过读取配置文件的beanName采用abstractBeanFactory.getBean(str)的方式获取下一个节点的对象
四、学习总结
收获:
1.复习了职责链模式
2.了解了Filter拦截对于职责链模式的运用
3.总结了职责链模式在五大原则指导下发挥的更加突出的作用
提出的问题(问题将在后续博文中解答):
1.职责链和状态模式的对比?
2.职责链和策略模式的对比?
五、升华
所谓天下武功唯快不破,天下代码唯设计模式不立,而设计模式再五大原则的强有力指导下会发挥更加突出的作用。