【设计模式】Chain of Responsibility 责任链式模式

一, 前言

责任链行为模式是行为模式的一种。

行为模式涉及到算法和对象间职责的分配,行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。

行为模式分为 :Template Method 模板方法 和 Interpreter 解析器行为模式。

模板方法:
是一个算法的抽象定义,它逐步地定义该算法,每一步调用抽象操作或一个原语操作,子类定义抽象操作以具体实现该算法。

解析器模式:
将一个文法表示为一个类层次,并实现一个解析器作为这些类的实例上的一个操作。

行为对象模式使用对象复合,而不是继承。

二、责任链—对象行为模式

1. 意图

使多个对象都用机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

2. 动机

. 根据普遍性(generality)即从最特殊到最普遍的顺序组织信息。
. 该模式的思想是,给多个对象处理一个请求的机会,从而解耦发送者和接收者。
. 要沿链转发请求,并保证接收者为隐式的 (implicit),每个在链上的对象都有一致的处理请求和访问链上后继者的接口。

3. 适用性

. 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
. 想在不明确指定接收者的情况下, 向多个对象中的一个提交了一个请求;
. 可处理一个请求的对象集合应被动态指定。

4. 结构

这里写图片描述

Handler
. 定义一个处理请求的接口;
. (可选) 实现后继链;

ConcreteHandler 继承 Handler
. 处理它所负责的请求;
. 可访问它的后继者;
. 如果可处理该请求,就处理之;否则将该请求转发给它的后继者。

Client
. 向链上的具体处理者 (ConcreteHandler)对象提交请求。

5. 效果
优点

(1). 降低耦合度
该模式使得一个对象无需知道是其他哪一个对象一个指向其后继者的引用,而不需保持它所有的后选者的引用;
责任链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。

(2). 增强了给对象指派职责(Responsibility)的灵活性
可以通过在运行时刻对该链进行动态的增加或修改来增加改变处理一个请求的那些职责。

缺点

不能保证被接受
请求没有明确的接收者,该请求可能一直到链的末端都得不到处理;也可能因该链没有被正确配置而得不到处理。

6. 实现需要考虑的问题
(1). 抽象处理者 Handler

. 定义一个请求的处理方法, HandleMessage, 对外开放的方法;
. 定义链的编排方法 setNext, 设置下一个处理者;
. 定义具体的请求者必须实现的两个方法:自己能够处理的级别 getHandleLevel 和具体的处理任务 echo;

(2). 具体处理者 ConcreteHandler

. 定义自己的处理逻辑;
. 设置自己的处理级别;

(3). 在场景类或高层模块中对链进行组装,并传递请求,并返回结果

三. 实例代码

抽象处理者

/**
 *  抽象处理者
 * @author Administrator
 *
 */
public abstract class Handler {

    private Handler nextHandler;

    // 每个处理者都必须对请求做出处理
    public final Response handMessage(Request request){
        Response response = null;
        // 判断是否是自己的处理级别
        if (this.getHandlerLevel().equals(request.getRequestLevel())) {
            response = this.echo(request);
        } else {    // 不属于自己的处理级别
            if (nextHandler != null) {
                response = nextHandler.handMessage(request);
            } else {
                // 没有适当的处理者,业务自行处理
            }
        }

        return response;
    }

    /**
     *  设置下一个处理者是谁
     * @param handler
     */
    public void setNext(Handler handler){
        this.nextHandler = handler;
    }

    // 每个处理者都有一个处理级别
    protected abstract Level getHandlerLevel();
    // 每个处理者都必须实现处理任务
    protected abstract Response echo(Request request);
}

具体处理者

// 具体处理者
public class ConcreteHandler1 extends Handler{

    // 定义自己的处理逻辑
    @Override
    protected Level getHandlerLevel() {
        // 完成处理逻辑
        return null;
    }

    // 设置自己的处理级别
    @Override
    protected Response echo(Request request) {
        // 设置自己的处理级别
        return null;
    }

}

封装请求等信息

public class Request {
    // 请求等级
    public Level getRequestLevel(){
        return null;
    }
}
public class Level {
    // 定义一个请求和处理等级
}
public class Response {
    // 处理者返回的数据
}

场景类

/**
 *  场景类
 * @author Administrator
 *
 */
public class Client {
    public static void main(String[] args) {
        // 声明所有的处理节点
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        Handler handler3 = new ConcreteHandler3();

        // 设置链中的阶段顺序1-->> 2-->> 3
        handler1.setNext(handler2);
        handler2.setNext(handler3);
        // 提交请求,返回结果
        Response response = handler1.handMessage(new Request());
    }
}

上面这个例子是正规的责任链模式,在 Android 的源码中也有责任链式模式,在输入系统中,将输入事件传递到 ViewRootImpl 时,就用到了。

 // Set up the input pipeline.
                CharSequence counterSuffix = attrs.getTitle();
                mSyntheticInputStage = new SyntheticInputStage();
                InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
                InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
                        "aq:native-post-ime:" + counterSuffix);
                InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
                InputStage imeStage = new ImeInputStage(earlyPostImeStage,
                        "aq:ime:" + counterSuffix);
                InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
                InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
                        "aq:native-pre-ime:" + counterSuffix);

详情参考 【读书笔记】Android 输入系统 一文。

其实还有一种变异类型,在 OkHttp 源码中
抽象类

public interface  Interceptor {

    Response intercept(Chain chain) throws IOException;


    interface Chain{
        Request request();

        Response proceed(Request request) throws IOException;

    }
}

具体实现类

public class BridgeInterceptor implements Interceptor{

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request userRequest = chain.request();

        Response networkResponse = chain.proceed(userRequest);

        System.out.println("BridgeInterceptor intercept");

        return networkResponse;
    }

}
public class CacheInterceptor implements Interceptor{

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        Response response = chain.proceed(request);

        System.out.println("CacheInterceptor intercept");
        return response;
    }

}
public class ConnectInterceptor implements Interceptor{

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        Response response = new Response();

        System.out.println("ConnectInterceptor intercept");
        return response;
    }

}
public class RealInterceptorChain implements Interceptor.Chain{

    private final List<Interceptor> interceptors;
    private final int index;
    private final Request request;
    private int calls;

    public RealInterceptorChain(List<Interceptor> interceptors, int index, Request request) {
        this.interceptors = interceptors;
        this.index = index;
        this.request = request;
    }

    @Override
    public Request request() {
        return request;
    }

    @Override
    public Response proceed(Request request) throws IOException {
        if (index >= interceptors.size()) {
            throw new AssertionError();
        }

        calls++;

        // Call the next interceptor in the chain.
        RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);

        // Confirm that the next interceptor made its required call to  chain.proceed().
        if (index + 1 < interceptors.size() && next.calls != 1) {
            throw new IllegalStateException("network interceptor " + interceptor
                    + " must call proceed() exactly once");
        }

        // Confirm that the intercepted response isn't null.
        if (response == null) {
            throw new NullPointerException("interceptor " + interceptor  + " returned null");
        }
        return response;
    }

}

场景类

public class TempClient {

    public static void main(String[] args) throws IOException {

        List<Interceptor> interceptors = new ArrayList<Interceptor>();
        interceptors.add(new BridgeInterceptor());
        interceptors.add(new CacheInterceptor());
        interceptors.add(new ConnectInterceptor());

        Request request = new Request();
        Interceptor.Chain chain = new RealInterceptorChain(interceptors, 0, request);
        chain.proceed(request);

        /**
         *  执行结果, 倒序
         *   ConnectInterceptor intercept
         *   CacheInterceptor intercept
         *   BridgeInterceptor intercept
         */
    }

}

注:1.本文综合《设计模式 可复用面向对象软件的基础》一书;
2. 《设计模式之禅》一书;
3. 上文中的的两个例子代码已放到 GitHub 上

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值