--- tags: Behavioral Patterns --- # 責任鏈模式 Chain Of Responsibility ## 目的 把訊息傳給適合的class去做處理,否則就傳給下一個。 舉例:去送一個文件,但被A窗口拒絕,並告知要去B窗口,接著又被B窗口拒絕後送去C窗口,這個文件才成功被處理。 ## 架構圖 ![](https://i.imgur.com/8KJoFTr.png) ## 打武器 範例 * 打鐵 (機率提升攻擊) * 鑲寶石 (機率提升特殊效果) * 加把手 (機率提升命中) * 取出 (出貨) ```java= abstract class Handler { Handler nextHandler = null; public Handler(Handler nextHandler) { this.nextHandler = nextHandler; } public void execute() { action(); if (nextHandler != null) { nextHandler.execute(); } } abstract void action(); } class ImproveAttackHandler extends Handler { public ImproveAttackHandler(Handler nextHandler) { super(nextHandler); } @Override void action() { System.out.println("Improve attack ability"); } } class HitsRateHandler extends Handler { public HitsRateHandler(Handler nextHandler) { super(nextHandler); } @Override void action() { System.out.println("Improve hits rate ability"); } } class SpecialAbilityHandler extends Handler { public SpecialAbilityHandler(Handler nextHandler) { super(nextHandler); } @Override void action() { System.out.println("Add special ability"); } } class FinishHandler extends Handler { public FinishHandler(Handler nextHandler) { super(nextHandler); } @Override void action() { System.out.println("Take out weapon from smithy"); } } public class ChainOfResponsibility { public static void main(String[] args) { System.out.println("Start to make a weapon"); Handler handler = new ImproveAttackHandler( new SpecialAbilityHandler( new HitsRateHandler( new FinishHandler(null) ) ) ); handler.execute(); } } ``` ## 範例1 ```java= // 所有處理郵件的子類別要繼承的介面 public abstract class MailHandler { // 每個處理郵件類別都要記錄下一個 // 能處理的人是誰 protected MailHandler mHandler; public MailHandler(MailHandler handler) { mHandler = handler; } public void toNext(Mail mail) { if(mHandler != null) { mHandler.handleMail(mail); } else { // 沒有後繼者, 表示是尾端了 // 通常可以用最一般化的處理 } } public abstract void handleMail(Mail mail); } public class SpamMailHandler extends MailHandler { SpamMailHandler(MailHandler handler){ super(handler); } @Override public void handleMail(Mail mail) { // 假設已經能知道郵件分類了 if(mail.isSpam()) { // 處理垃圾信 } else { toNext(mail); } } } public class ThankMailHandler extends MailHandler { // 假設已經能知道郵件分類了 if(mail.isThank()) { // 處理感謝信 } else { toNext(mail); } } public class ComplainMailHandler extends MailHandler { // 假設已經能知道郵件分類了 if(mail.isComplain()) { // 處理Complain } else { toNext(mail); } } public class GeneralMailHandler extends MailHandler { if(mail.isGeneral()) { // 處理General } else { toNext(mail); } } public class Main { public static void main(String[] args) { // 可以這樣使用 MailHandler handler = new ThankMailHandler( new ComplainMailHandler( new SpamMailHandler( new GeneralMailHandler(null)))); // 假設有一封郵件要處理 Mail mail = new Mail(...); handler.hanldeMail(mail); } } ``` ## 範例2 ```java= public abstract class Support { private String name; // 問題解決者的名稱 private Support next; // 轉送位置 public Support(String name) { // 產生問題解決者 this.name = name; } public Support setNext(Support next) { // 設定轉送位置 this.next = next; return next; } public final void support(Trouble trouble) { // 解決問題的步驟 if (resolve(trouble)) { done(trouble); } else if (next != null) { next.support(trouble); } else { fail(trouble); } } public String toString() { // 列印字串 return "[" + name + "]"; } protected abstract boolean resolve(Trouble trouble); // 解決的方法 protected void done(Trouble trouble) { // 已解決 System.out.println(trouble + " is resolved by " + this + "."); } protected void fail(Trouble trouble) { // 尚未解決 System.out.println(trouble + " cannot be resolved."); } } public class SpecialSupport extends Support { private int number; // 只能解決此號碼的問題 public SpecialSupport(String name, int number) { // 建構子 super(name); this.number = number; } protected boolean resolve(Trouble trouble) { // 解決的方法 if (trouble.getNumber() == number) { return true; } else { return false; } } } public class OddSupport extends Support { public OddSupport(String name) { // 建構子 super(name); } protected boolean resolve(Trouble trouble) { // 解決的方法 if (trouble.getNumber() % 2 == 1) return true; } else { return false; } } } public class NoSupport extends Support { public NoSupport(String name) { super(name); } protected boolean resolve(Trouble trouble) { // 解決的方法 return false; // 自己不做處理 } } public class LimitSupport extends Support { private int limit; // 若小於此號碼則可解決問題 public LimitSupport(String name, int limit) { // 建構子 super(name); this.limit = limit; } protected boolean resolve(Trouble trouble) { // 解決的方法 if (trouble.getNumber() < limit) { return true; } else { return false; } } } public class Trouble { private int number; // 問題編號 public Trouble(int number) { // 發生問題 this.number = number; } public int getNumber() { // 取得問題編號 return number; } public String toString() { // 列印顯示問題的字串 return "[Trouble " + number + "]"; } } public class Main { public static void main(String[] args) { Support alice = new NoSupport("Alice"); Support bob = new LimitSupport("Bob", 100); Support charlie = new SpecialSupport("Charlie", 429); Support diana = new LimitSupport("Diana", 200); Support elmo = new OddSupport("Elmo"); Support fred = new LimitSupport("Fred", 300); // 形成連鎖 alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred); // 發生各種問題 for (int i = 0; i < 500; i += 33) { alice.support(new Trouble(i)); } } } ```