設計模式 | 職責鏈模式(Chain of responsibility)
定義:
使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。將這個對象連城一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
結構:(書中圖,侵刪)
一個抽象的處理者
若干個具體處理者(每個具體處理者都不知道它的繼任者是誰,這個繼任者由客戶端決定,只負責把處理不了的請求轉發給繼任者)
實例:
工作流基本都可以用這個模式來設計。
我就來寫個生產醬板鴨的流水線好了。
屠宰-》清洗-》滷製-》風乾-》包裝
簡化一點,懶得寫那麼多類
清洗-》滷製-》包裝
鴨子類:
package designpattern.chainofresponsibility; public class Duck { public State state; Duck(State state) { this.state = state; } public enum State { DIRTY, CLEAN, COOKED, PACKAGED } public State getState() { return state; } public void setState(State state) { this.state = state; } }
抽象處理者類:
package designpattern.chainofresponsibility; public abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void handleDuck(Duck duck); }
清洗者類(具體處理者):
package designpattern.chainofresponsibility; import designpattern.chainofresponsibility.Duck.State; public class DuckCleaner extends Handler { @Override public void handleDuck(Duck duck) { if (duck.state == State.DIRTY) { System.out.println("清洗員-》清理鴨子~"); duck.setState(State.CLEAN); } else { successor.handleDuck(duck); } } }
廚師類(具體處理者):
package designpattern.chainofresponsibility; import designpattern.chainofresponsibility.Duck.State; public class DuckCook extends Handler { @Override public void handleDuck(Duck duck) { if (duck.state == State.CLEAN) { System.out.println("廚師-》滷製鴨子~"); duck.setState(State.COOKED); } else { successor.handleDuck(duck); } } }
打包者類(具體處理者):
package designpattern.chainofresponsibility; import designpattern.chainofresponsibility.Duck.State; public class DuckPackager extends Handler { @Override public void handleDuck(Duck duck) { if (duck.state == State.COOKED) { System.out.println("打包員-》包裝鴨子~"); duck.setState(State.PACKAGED); } } }
客戶端:
package designpattern.chainofresponsibility; import designpattern.chainofresponsibility.Duck.State; public class Client { public static void main(String[] args) { DuckCleaner duckCleaner = new DuckCleaner(); DuckCook duckCook = new DuckCook(); DuckPackager duckPackager = new DuckPackager(); duckCleaner.setSuccessor(duckCook); duckCook.setSuccessor(duckPackager); // 處理臟鴨子 Duck duck = new Duck(State.DIRTY); duckCleaner.handleDuck(duck); // 處理鹵好的鴨子 duck.setState(State.COOKED); duckCleaner.handleDuck(duck); } }
結果輸出:
清洗員-》清理鴨子~
打包員-》包裝鴨子~
不管鴨子在哪個狀態,統統傳給清理者,他處理不了,會一路傳下去,直到正確的人來處理。
總結:
這個模式算是一個結構比較簡單的,也很好理解,只不過之前自己想的時候完全沒有想出來可以用這樣的方式來實現。
又能把請求傳遞下去又能讓處理者之間,以及處理者和客戶端之間解耦,真的很巧妙。
不過像上面說的,繼任者是由客戶端決定的,但實際上具體處理者之間有潛在的邏輯關係,如果客戶端沒有正確的設置鏈條可能會導致請求得不到處理。
比如上面的例子,直接拿洗好的鴨子去包裝顯然是包裝不了的。
所以需要把文檔寫得足夠清晰,以供客戶端正確使用。