Chain of responsibility-責任鏈模式

fulton發表於2019-02-14

解決問題

它主要解決的問題是“遞迴、迴圈”問題或者大量的if-else 問題。通過定義不通的receiver,並在執行時決定receiver的執行順序。它帶來的一個好處是:receiver邏輯耦合(可以分不同的場景劃分receiver邏輯), 程式碼結構清晰。

應用場景

資訊或者請求 需要經過大量的if-else處理(轉換成由多個receiver中的其中一個進行處理);

資訊或請求 需要進行流水線處理(即需要經過層層加工)

原理圖(UML)

Chain of responsibility-責任鏈模式

Handler:持有nextHander物件,以便交下一個鏈條;並持有一個handle方法來處理請求

Receiver:實現Handler介面,並實現具體的處理邏輯

Sender:生成具有一定處理順序的鏈條,並啟動鏈條的頭部來處理請求。

示例

這裡我們舉一個場景:去飯店吃飯,首先我們要向點餐員點菜、然後點餐員將菜名報給廚師、廚師做完菜之後將菜端到我們面前。

public abstract class Handler {

    protected Handler nextHandler;
    public abstract void handle();

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
}
public class OrderTaker extends Handler {

    @Override
    public void handle() {
        System.out.println("請客人點餐");
        System.out.println("客人點餐完成");
        if (this.nextHandler != null) {
            nextHandler.handle();
        } else {
            System.out.println("廚師下班了。。。");
        }
    }
}

public class Cooker extends Handler {

    @Override
    public void handle() {
        System.out.println("為客人做菜");
        System.out.println("做菜完成");
        if (this.nextHandler != null) {
            nextHandler.handle();
        } else {
            System.out.println("該招送餐員了。。。。");
        }
    }
}

public class Deliver extends Handler {

    @Override
    public void handle() {
        System.out.println("將菜送到客人面前");
    }
}

public class Manager {
    public static void main(String[] args) {
        // 組織結構
        OrderTaker orderTaker = new OrderTaker();
        Cooker cooker = new Cooker();
        Deliver deliver = new Deliver();
        orderTaker.setNextHandler(cooker);
        cooker.setNextHandler(deliver);
        // 來一個客人
        orderTaker.handle();
    }
}
複製程式碼

下面的這種形式是一個變種,但其在各種基本元件中應用則更為廣泛

spring -filter/interceptor都是採用的該模式,下面貼一部分OkHtpp中的對請求的處理原始碼。該示例參考:https://blog.csdn.net/yxhuang2008/article/details/72566928

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
         */
    }

}
複製程式碼

參考

相關文章