責任鏈模式——使編程更有靈活性

(《設計模式解析與實戰——何紅輝,關愛民》讀書筆記)

一、定義
使多個對象都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關係。將這些對象連成一條線,並沿着這條鏈傳遞該請求,直到有對象處理它爲止。
這類似於力的傳遞一樣,一環套一環。
二、使用場景
(1)多個對象可以處理同一請求,但具體由哪個對象處理則在運行時動態決定;
(2)在請求處理者不明確的情況下向多個對象中的一個提交一個請求;
(3)需動態指定一組對象處理請求。
三、責任鏈模式的通用模式代碼
簡化版的通用模式代碼:
Handler:抽象處理者角色,聲明一個請求處理的方法,並在其中保持一個對下一個處理節點Handler對象的引用。
ConcreteHandler:具體處理者角色,對請求進行處理,如果不能處理則將該請求轉發給下一個節點上的處理對象。


/**
 * 抽象處理者
 */
public abstract class Handler {
    /**
     *  下一節點處理者
     */
    protected Handler successor;

    /**
     * 請求處理
     * 
     * @param condition
     *            請求條件
     */
    public abstract void handlerRequest(String condition);
}
/**
 * 具體的處理者1
 */
public class ConcreteHandler1 extends Handler{

    @Override
    public void handlerRequest(String condition) {
        if (condition.equals("ConcreteHandler1")) {
            System.out.println("我是具體的處理者1");
            return;
        }else {
            successor.handlerRequest(condition);
        }
    }

}
/**
 * 具體的處理者2
 */
public class ConcreteHandler2 extends Handler{

    @Override
    public void handlerRequest(String condition) {
        if (condition.equals("ConcreteHandler2")) {
            System.out.println("我是具體的處理者2");
            return;
        }else {
            successor.handlerRequest(condition);
        }
    }

}
/**
 * 客戶端
 */
public class Client {
    public static void main(String[] args) {

        ConcreteHandler1 handler1 = new ConcreteHandler1();
        ConcreteHandler2 handler2 = new ConcreteHandler2();

        // 設置handler1的下一節點
        handler1.successor = handler2;
        // 設置handler2的下一節點
        handler2.successor = handler1;

        // 處理請求
        handler1.handlerRequest("ConcreteHandler2");
    }
}

運行結果:
這裏寫圖片描述

上面的請求條件是一個字符串,然而在大多數情況下,責任鏈中的請求和對應的處理規則是不盡相同的,在這種情況下可以將請求進行封裝,同時對請求的處理規則也進行封裝作爲一個獨立的對象。

**
 * 抽象請求者
 */
public abstract class AbstractRequest {
    /**
     * 處理對象
     */
    private Object mObject;

    public AbstractRequest(Object object) {
        super();
        this.mObject = object;
    }

    /**
     * 獲取處理的內容對象
     * 
     * @return 具體的內容對象
     */
    public Object getContent() {
        return mObject;
    }

    /**
     * 獲取請求級別
     * 
     * @return 請求級別
     */
    public abstract int getRequestLevel();
}
/**
 * 抽象處理者
 */
public abstract class AbstractHandler {
    /**
     * 下一節點上的處理者對象
     */
    protected AbstractHandler nextHandler;

    /**
     * 處理請求
     * 
     * @param request
     *            請求對象
     */
    public final void handlerRequest(AbstractRequest request) {
        // 判斷當前處理者對象的處理級別是否與請求者的處理級別一致
        if (getHanleLevel() == request.getRequestLevel()) {
            // 一致則由該處理對象處理
            handle(request);
        } else {
            // 否則將該請求對象轉發給下一個節點上的請求對象
            if (nextHandler != null) {
                nextHandler.handlerRequest(request);
            } else {
                // 當所有處理者對象均不能處理該請求時輸出
                System.out.println("All of handler can not handle the request!");
            }
        }
    }

    /**
     * 獲取處理者對象的具體處理級別
     * 
     * @return 處理級別
     */
    protected abstract int getHanleLevel();

    /**
     * 獲取處理者對象的具體處理方式
     * 
     * @param request
     *            請求者對象
     */
    protected abstract void handle(AbstractRequest request);
}
/**
 * 請求者1
 */
public class Request1 extends AbstractRequest{

    public Request1(Object object) {
        super(object);
    }

    @Override
    public int getRequestLevel() {
        return 1;
    }
}
/**
 * 請求者2
 */
public class Request2 extends AbstractRequest{

    public Request2(Object object) {
        super(object);
    }

    @Override
    public int getRequestLevel() {
        return 2;
    }
}
/**
 * 請求者3
 */
public class Request3 extends AbstractRequest{

    public Request3(Object object) {
        super(object);
    }

    @Override
    public int getRequestLevel() {
        return 3;
    }
}

/**
 * 處理者1
 */
public class Handler1 extends AbstractHandler {

    @Override
    protected int getHanleLevel() {
        return 1;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handler1 handle request:" + request.getRequestLevel());
    }
}
/**
 * 處理者2
 */
public class Handler2 extends AbstractHandler {

    @Override
    protected int getHanleLevel() {
        return 2;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handler2 handle request:" + request.getRequestLevel());
    }
}
/**
 * 處理者3
 */
public class Handler3 extends AbstractHandler {

    @Override
    protected int getHanleLevel() {
        return 3;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handler3 handle request:" + request.getRequestLevel());
    }
}
/**
 * 客戶端
 */
public class Client {
    public static void main(String[] args) {
        // 構造三個處理者對象
        AbstractHandler handler1 = new Handler1();
        AbstractHandler handler2 = new Handler2();
        AbstractHandler handler3 = new Handler3();

        // 設置當前處理者對象下一個節點的處理者對象
        handler1.nextHandler = handler2;
        handler2.nextHandler = handler3;

        // 構造三個請求者對象
        AbstractRequest request1 = new Request1("Request1");
        AbstractRequest request2 = new Request1("Request2");
        AbstractRequest request3 = new Request1("Request3");

        // 總是從鏈式的首端發起請求
        handler1.handlerRequest(request1);
        handler1.handlerRequest(request2);
        handler1.handlerRequest(request3);
    }
}

運行結果:
這裏寫圖片描述
當然請求的發起可以從責任鏈的任何一個節點處開始,同時也可以改變責任鏈內部傳遞的規則。

四、優缺點
優點:
可以對請求者和處理者關係解耦,提高代碼的靈活性。
缺點:
對請求處理者的遍歷,如果處理者太多那麼遍歷必定會影響性能,特別是在一些遞歸調用中,要慎重。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章