模式定义与设计解读
设计模式晦涩的定义总是难懂, 但同时这些定义又有着独特的涵义. 本文想通过最直观的例子, 把这些晦涩的定义反应在代码层面上. 代码是设计模式最直观的表达, 当你看不懂定义时, 代码会说话. 希望这篇解读可以帮助到你. 预计阅读 10 分钟.
定义
责任链模式 : 使多个对象有机会处理请求, 从而避免了请求的发送者和接收者之间的耦合关系. 将这些对象连成一条链, 并沿着这条链传递该请求, 直到有对象处理它为止.
注意一下加粗的关键字, 解读会重新定义这些难懂的定义.
解读
在生活经常存在一种场景, 完成一件事情, 需要串行执行几个步骤. 比如把大象装冰箱, 需要三个步骤.
把冰箱门打开
把大象装冰箱
把冰箱门关上
现在把这件事情抽象成代码, 并与上文中的定义对应.
请求指把大象装冰箱这件事情, 对应一个数据结构 RequestContext.
- /**
- * 请求上下文
- */
- public class RequestContext {
- public Elephant mElephant;// 大象
- public Refrigerator mRefrigerator;// 冰箱
- public RequestContext(Elephant elephant, Refrigerator refrigerator) {
- mElephant = elephant;
- mRefrigerator = refrigerator;
- }
- public static class Elephant{
- }
- public static class Refrigerator{
- }
- }
一条链比较好理解, 但是比较难抽象. 既然做这件事需要串行好几个步骤, 链条上自然也是围绕请求展开, 既需要有获取请求的方法
RequestContext getContext()
, 也需要有执行请求的方法
procceed(RequestContext context)
. 这个方法有开始执行的意思, 也有请求串行传递后继续执行的意思.
proceed 英 [prə'siːd]
vi. 开始; 继续进行; 发生;
- /**
- * 请求链
- */
- public interface Chain {
- /**
- * 获取请求实体
- */
- RequestContext getContext();
- /**
- * 开始或继续执行请求.
- */
- void proceed(RequestContext context);
- }
对象指 1.2.3 操作大象和冰箱的三个步骤, 可以把每次步抽象成一个处理请求的对象, 万物皆对象. 现在我们已经把请求封装在了链条里, 那对于每个操作步骤, 都直接来处理链条上的请求即可.
- /**
- * 处理者
- */
- public interface Handler {
- /**
- * 处理链条上的请求
- */
- void handle(Chain chain);
- }
发送者和接收者其实是指操作步骤的动作. 每个操作步骤都会有以下流程
先接收请求(接收)
处理请求 (处理)
通知 Chain, 继续执行请求.(发送)
每个操作步骤只需要关注自己需要如何操作请求, 而不需要关心操作完成后下个步骤是什么. 只需要通知 Chain, 我执行完毕了, 可以继续执行下一步了. 从而避免了发送者和接收者之间的耦合关系. 那么如何解耦呢, 自然是链条来解决. 链条上持有一系列操作步骤, 存储成 List<Handler>, 并且记录当前执行到第几步 int index, 再结合之前定义的 Chain 接口, Chain 实现类如下
- /**
- * 链实现类
- */
- public class ProcessChain implements Chain {
- public List<Handler> mProcessors;
- public RequestContext mChainContext;
- public int mIndex;
- public ProcessChain(List<Handler> processors, int index, RequestContext chainContext) {
- mProcessors = processors;
- mIndex = index;
- mChainContext = chainContext;
- }
- @Override
- public RequestContext getContext() {
- return mChainContext;
- }
- @Override
- public void proceed(RequestContext processContext) {
- if (mProcessors.size()> mIndex) {
- // 获取当前处理者
- Handler processor = mProcessors.get(mIndex);
- // 更新 index 与 Context
- ProcessChain nextChain = new ProcessChain(mProcessors, mIndex + 1, processContext);
- // 处理者执行处理步骤
- processor.handle(nextChain);
- }
- }
- }
proceed 方法可能会觉得有些绕, 其实道理很简单. 着重理解一下 nextChain 即可, 这里是重新构造了一个 Chain, 其实也可以理解为更新了一下 Chain 的数据, 将 index+1, 以及更新 RequestContext . 接下来讲到 Processor 的实现类, 二者结合起来理解会更容易 nextChain.
Handler 实现类. 接收的概念好理解, 就是接口方法 handle(Chain chain)中的参数. 那么什么是发送呢, 我们回到上文 nextChain, 实际
handle(Chain chain)
方法接收的参数就是下个节点的 Chain, 我们只需要在 handle()方法中处理完毕后, 继续调用 chain.proceed()方法, 通知链条继续执行就可以了. 请求就这样被发送出去了.
- /**
- * 打开冰箱
- */
- public class HandlerOpenRefrigerator implements Handler {
- @Override
- public void handle(Chain chain) {
- RequestContext requestContext = chain.getContext();
- // 处理具体操作
- if(!requestContext.mRefrigerator.isOpen()) {
- requestContext.mRefrigerator.open();
- }
- // 处理完毕 继续执行下个操作
- chain.proceed(requestContext);
- }
- }
拦截器 当我们执行到第二步时, 需要装大象, 如果这时候门没打开怎么办? 任务执行不下去, 我们可以选择中断链条, 退出本次串行任务. 这种链条上的任务传递和适当时机终止结合起来就是我们经常说的拦截器. 拦截器就是基于责任链模式, 每个节点有自己的职责, 同时可以选择是否把任务传递给下一个环节
- /**
- * 移动大象
- */
- public class MoveElephantHandler implements Handler {
- @Override
- public void handle(Chain chain){
- RequestContext requestContext = chain.getContext();
- // 处理具体操作
- if(requestContext.mRefrigerator.isOpen()) {
- requestContext.mElephant.move();
- // 处理完毕 继续执行下个操作
- chain.proceed(requestContext);
- }else{
- // 发生异常 中断链条
- chain.abort();
- }
- }
- }
- public class MyClass {
- public static void main(String[] args) {
- // 构造请求
- RequestContext requestContext = new RequestContext(new RequestContext.Elephant(),new RequestContext.Refrigerator());
- // 构造处理步骤
- List<Handler> list = new ArrayList<>();
- // 你也可以不加打开冰箱试试结果
- list.add(new OpenRefrigeratorHandler());
- list.add(new MoveElephantHandler());
- list.add(new CloseRefrigeratorHandler());
- // 执行任务
- ProcessChain processChain = new ProcessChain(list,0,requestContext);
- processChain.proceed(requestContext);
- }
- }
- /**
- * Observes, modifies, and potentially short-circuits requests going out and the corresponding
- * responses coming back in. Typically interceptors add, remove, or transform headers on the request
- * or response.
- */
- public interface Interceptor {
- Response intercept(Chain chain) throws IOException;
- interface Chain {
- Request request();
- Response proceed(Request request) throws IOException;
- }
- }
来源: http://www.jianshu.com/p/ef200622c4b7