汕头站扩建进展,wordpress 后台加速,7网站建设1,如何把网站转网站责任链模式属于行为设计模式#xff0c;常见的过滤器链就是使用责任链模式设计的。 文章目录 1、真实开发场景的问题引入2、责任链模式讲解2.1 核心类及类图2.2 基本代码 3、利用构建者模式解决问题4、责任链模式的应用实例5、总结5.1 解决的问题5.2 使用场景5.3 优缺点 1、真… 责任链模式属于行为设计模式常见的过滤器链就是使用责任链模式设计的。 文章目录 1、真实开发场景的问题引入2、责任链模式讲解2.1 核心类及类图2.2 基本代码 3、利用构建者模式解决问题4、责任链模式的应用实例5、总结5.1 解决的问题5.2 使用场景5.3 优缺点 1、真实开发场景的问题引入
Q假设有一个闯关游戏共三关每一关达到通过条件后才能进入下一关使用java实现。 A针对这个问题按照朴素的想法我们可以定义三个类分别是第一关、第二关、第三关客户端启动游戏首先进入第一关然后第一关通过后进入第二关依次类推。我们可以得到这样的代码如下
Slf4j
public class FirstLevel {Autowiredprivate SecondLevel secondLevel;public void play(){log.info(进入第一关);//游戏操作,获得分数int res 80;if(res 80){secondLevel.play();}else {return;}}
}
Component
Slf4j
public class SecondLevel {Autowiredprivate ThirdLevel thirdLevel;public void play(){log.info(进入第二关);//游戏操作,获得分数int res 90;if(res 90){thirdLevel.play();}else {return;}}
}
Component
Slf4j
public class ThirdLevel {public void play(){log.info(进入第三关);//游戏操作,获得分数int res 95;if(res 95){log.info(游戏通关);}else {return;}}
}SpringBootTest
RunWith(SpringRunner.class)
Slf4j
class DpApplicationTests {Autowiredprivate FirstLevel firstLevel;Testpublic void client(){firstLevel.play();}
}上述代码有什么问题呢
耦合性太强每个类中包含其他类如果想改变关卡的顺序需要改类内部代码
2、责任链模式讲解
责任链模式应用的场景是一个请求有很多处理者可以处理这些处理者构成一个链请求只需要发送到链上不用管最终是谁处理了请求也不用管请求在链上是怎么传递的。这样就实现了请求者与被请求者的解耦同时也只需定义一条链把处理者放到链上同时定义好处理者的顺序处理者之间也不用相互持有。
2.1 核心类及类图 一个抽象处理器接口和三个具体的处理器在处理器链类中有一个List其中放的是三个具体处理器在客户端中使用处理器链对象与请求交互。
2.2 基本代码
1 定义一个处理器返回结果类型其中包括处理结果数据(范型)、是否继续在链上传播
Data
public class ProcessResultR {private boolean next;private R data;public ProcessResult(boolean next, R data) {this.next next;this.data data;}/*** 继续处理并返回数据* param data* param R* return*/public static R ProcessResult resumeData(R data){return new ProcessResult(true,data);}/*** 继续处理不返回数据* param R* return*/public static R ProcessResult resumeNoData(){return new ProcessResult(true,null);}/*** 不继续处理返回数据* param R* return*/public static R ProcessResult stopData(R data){return new ProcessResult(false,data);}/*** 不继续处理不返回数据* param R* return*/public static R ProcessResult stopNoData(){return new ProcessResult(false,null);}
}
2 定义抽象的处理器返回值为上面定义的类型有两个范型一个是处理器接收的参数另一个是处理器返回具体数据的类型包裹在ProcessResult中
public interface ProcessorResult,Param {/*** 使用范型的方法、类需要指定范型* param param 处理器参数* return Res 返回结果*/ProcessResultResult process(Param param );/*** 接口的默认方法表示该处理器是否已经处理过请求* return*/default boolean isProcessed(){return false;}
}3 定义三个具体的处理器用来处理请求使用order注解规定了JavaBean扫描的顺序实现Processor注意指明范型参数
Component
Order(1)
Slf4j
public class ConcreteProcessor01 implements ProcessorString,String{Overridepublic ProcessResultString process(String s) {//通过参数判断是不是处理请求log.info(ConcreteProcessor01处理);//处理return ProcessResult.resumeData(s);}
}
Component
Order(2)
Slf4j
public class ConcreteProcessor02 implements ProcessorString,String{Overridepublic ProcessResultString process(String s) {//通过参数判断是不是处理请求log.info(ConcreteProcessor02处理);//处理return ProcessResult.stopData(s);}
}
Component
Order(3)
Slf4j
public class ConcreteProcessor03 implements ProcessorString,String{Overridepublic ProcessResultString process(String s) {//通过参数判断是不是处理请求log.info(ConcreteProcessor03处理);//处理return ProcessResult.resumeData(s);}
}4 定义处理器链构造函数注入List类型参数spring容器会扫描所有的P类型的Bean放到List中。ProcessorResult,Param 前面定义的ConcreteProcessor01、02、03一致即ProcessorString,String但是这里为了保证BaseChain的通用性即可以定义多个聚合不同类型处理器的处理器链该处使用范型。
Component
Slf4j
public class BaseChainResult,Param {private ListProcessorResult,Param processors;Autowiredpublic BaseChain(ListProcessorResult,Param processors) {this.processors processors;}public void doProcess(Param param) {for (Processor processor : processors) {ProcessResult process processor.process(param);if (process.getData() ! null) {log.info(process.getData().toString());}if (!process.isNext()) {return;}}}
}5 客户端
SpringBootTest
RunWith(SpringRunner.class)
Slf4j
class DpApplicationTests {Autowiredprivate BaseChain baseChain;Testpublic void chainTest(){baseChain.doProcess(123);}
}
输出
3、利用构建者模式解决问题
针对1中的问题可以套用2中的代码解决
4、责任链模式的应用实例 Spring Web 中的 HandlerInterceptor HandlerInterceptor接口在web开发中非常常用里面有preHandle()、postHandle()、afterCompletion()三个方法preHandle()方法在请求处理之前被调用、postHandle()方法在请求处理完成后但在视图渲染之前被调用、afterCompletion()方法在视图渲染完成后被调用
public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Nullable Exception ex) throws Exception {}
}这样的过滤器会有很多个使用责任链模式将这些过滤器放在一个链中即HandlerExecutionChain中由HandlerExecutionChain对所有的HandlerInterceptor进行调用。
public class HandlerExecutionChain {...//在数组中存放所有的过滤器Nullableprivate HandlerInterceptor[] interceptors;//数组的下标private int interceptorIndex -1;//pre的调度boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {HandlerInterceptor[] interceptors getInterceptors();if (!ObjectUtils.isEmpty(interceptors)) {for (int i 0; i interceptors.length; i) {//遍历过滤器HandlerInterceptor interceptor interceptors[i];//preHandle返回false进入该if结束处理流程if (!interceptor.preHandle(request, response, this.handler)) {//执行渲染完成后的逻辑triggerAfterCompletion(request, response, null);return false;}//修改当前指向的过滤器下标记录最后一个成功执行preHandle()方法的拦截器的索引。//如果某个拦截器的preHandle()方法返回false则遍历将停止并且请求处理也将停止。//在这种情况下HandlerExecutionChain需要调用所有已成功执行preHandle()方法的拦截器的afterCompletion()方法。//这时候就需要使用interceptorIndex得到最后一个成功执行的preHandle方法所在的拦截器在拦截链的位置。this.interceptorIndex i;}}return true;}
}
5、总结
5.1 解决的问题
职责链上的处理者负责处理请求客户只需要将请求发送到职责链上即可无须关心请求的处理细节和请求的传递所以职责链将请求的发送者和请求的处理者解耦了。
5.2 使用场景
在处理消息的时候以过滤很多道。
5.3 优缺点
优点 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点 1、不能保证请求一定被接收。 2、系统性能将受到一定影响而且在进行代码调试时不太方便可能会造成循环调用。 3、可能不容易观察运行时的特征有碍于除错。 参考 [1] 实战设计模式之责任链设计模式深度解析 [2] 责任链模式在 Spring 中的应用 [3] 责任链模式-菜鸟教程