【設計模式】——裝飾模式VS職責鏈模式

關於裝飾模式介紹,還請大家移步【設計模式】——裝飾器模式VS代理模式,本文主要介紹職責鏈模式,比較兩者的不同之處

職責鏈模式(行爲型)

定義: 使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。

主要解決:職責鏈上的處理者負責處理請求,客戶只需要將請求發送到職責鏈上即可,無須關心請求的處理細節和請求的傳遞,所以職責鏈將請求的發送者和請求的處理者解耦了。

何時使用:在處理消息的時候以過濾很多道。

如何解決:攔截的類都實現統一接口。

關鍵代碼:Handler 裏面聚合它自己,在 HandlerRequest 裏判斷是否合適,如果沒達到條件則向下傳遞,向誰傳遞之前 set 進去。

應用實例: 1、紅樓夢中的"擊鼓傳花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 對 Encoding 的處理,Struts2 的攔截器,jsp servlet 的 Filter。

優點: 1、降低耦合度。它將請求的發送者和接收者解耦。 2、簡化了對象。使得對象不需要知道鏈的結構。 3、增強給對象指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。 4、增加新的請求處理類很方便。

缺點: 1、不能保證請求一定被接收。 2、系統性能將受到一定影響,而且在進行代碼調試時不太方便,可能會造成循環調用。 3、可能不容易觀察運行時的特徵,有礙於除錯。

使用場景: 1、有多個對象可以處理同一個請求,具體哪個對象處理該請求由運行時刻自動確定。 2、在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。 3、可動態指定一組對象處理請求。

實現代碼

public abstract class Handler {

    protected Handler successor;

    //設置繼任者
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void HandleRequest(int request);
}
public class ConcreteHandler1 extends Handler {
    @Override
    public void HandleRequest(int request) {
        if (request > 0 && request < 10) {
            System.out.println("ConcreteHandler1通過");
        } else {
            successor.HandleRequest(request);
        }
    }
}
public class ConcreteHandler2 extends Handler {
    @Override
    public void HandleRequest(int request) {
        if (request > 10 ) {
            System.out.println("ConcreteHandler2通過");
        }
    }
public class Client {
    public static void main(String[] args) {
        Handler handler1 = new ConcreteHandler1();

        Handler handler2 = new ConcreteHandler2();

        handler1.setSuccessor(handler2);

        int[] requests = {2, 5, 14, 22};
        for (int request : requests) {
            handler1.HandleRequest(request);
        }
    }
}

關鍵點:當客戶提交請求時,請求是沿鏈傳遞直至有一個ConcreteHandler對象負責處理它。這使得接受者和發送者都沒有對方的明確信息,且鏈中對象自己也並不知道鏈的結構。職責鏈可以簡化對象的相互連接,它們僅需要保持一個指向其後繼者的引用,而不需要保持它所有的候選接收者的引用。可以隨時的增加或者修改處理一個請求的結構,增強了給對象指派職責的靈活性。

裝飾VS職責鏈兩者相同點以及不同點

相同點:都能對對象的處理進行增強

不同點:

裝飾者模式 持有被裝飾的對象,並具備被裝飾者的行爲,對其行爲進行補充增強。裝飾者它可以對某一類的對象進行增強,這樣就避免了冗餘的繼承體系,使得擴展性很強。

職責鏈模式 每個被調用者都持有下一個被調用者的引用,客戶端只需要發起一次調用即可。核心思想就是分而治之。當調用者面臨的被調者太多時,爲了降低邏輯複雜度,把相關的被調用者組織起來,形成一個鏈式的結構,被調用者之間進行調用傳遞(責任傳遞)。

職責鏈和裝飾器模式結合體

面對日常業務開發,有一種場景,需要使用職責鏈和裝飾器模式組合才能完成業務。如果單獨只想使用一種,就特別容易將兩個模式搞得界線很模糊。就用一種結合體將具體闡述下兩者使用的不同之處。

將Component的具體邏輯從由一個對象執行,改爲鏈路判斷,符合的執行,否則傳遞給下者。但是裝飾器Decorator並不關心具體是哪個對象執行此邏輯,只關心此邏輯執行後,它本身需要處理哪些邏輯。

具體邏輯代碼,以及結果輸出展示

//充當抽象角色,不應該具體實現
public interface Component {

    void Operation(int request);
}
//針對接口封裝抽象類,以便後續可以設置繼任者
public abstract class Handler implements Component {

    protected Handler successor;

    //設置繼任者
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    @Override
    public abstract void Operation(int request);
}

//具體邏輯1
public class ConcreteHandler1 extends Handler {
    @Override
    public void Operation(int request) {
        if (request > 0 && request < 10) {
            System.out.println(request + "對象操作 ConcreteHandler1通過");
        } else {
            successor.Operation(request);
        }
    }

}
//具體邏輯2
public class ConcreteHandler2 extends Handler {
    @Override
    public void Operation(int request) {
        if (request > 10 ) {
            System.out.println(request + "對象操作 ConcreteHandler2通過");
        }
    }
}
//裝飾抽象類繼承Component
public abstract class Decorator implements Component {

    //裝飾器的核心
    protected Component component;

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void Operation(int request) {
        if (component != null) {
            component.Operation(request);
        }
    }
}
//裝飾的具體實現類
public class ConcreteDecoratorA extends Decorator {

    @Override
    public void Operation(int request) {
        super.Operation(request);
        System.out.println("具體裝飾對象A的操作");
    }
}
public class ConcreteDecoratorB extends Decorator {
    @Override
    public void Operation(int request) {
        super.Operation(request);
        System.out.println("具體裝飾對象B的操作");
    }
}
public class Client {
    public static void main(String[] args) {
        //對象具體實現,但是不知道要使用鏈上的哪個類
        Handler handler1 = new ConcreteHandler1();

        Handler handler2 = new ConcreteHandler2();

        handler1.setSuccessor(handler2);

       ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
       ConcreteDecoratorB decoratorB = new ConcreteDecoratorB();

        decoratorA.setComponent(handler1);
        decoratorB.setComponent(decoratorA);

        int[] requests = {2, 5, 14, 22};
        for (int request : requests) {
            decoratorB.Operation(request);
        }
    }
}

 

圖中紅色方塊中,裝飾和職責鏈融合的開始,只將職責鏈的頂端當做被裝飾者,具體被裝飾者內部的邏輯則屬於職責鏈範圍。裝飾器模式,只要執行Operation(int request)方法就會對該方法執行內容增加額外處理,即增強。

總結

職責鏈模式:只關心被調用者之間的調用傳遞。

裝飾器模式:它不關心外界如何調用,只注重對對象功能的加強,裝飾後還是對象本身。

代理模式:重心是爲了借用對象的功能完成某一流程,而非對象功能如何。 

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