責任鏈模式

  • 定義:
    在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織和分配責任。

  • UML:

    • 時序圖:
      image.png
    • 從上圖我們可以看到,客戶端首先創(chuàng)建了2個處理器ConcreteHandler,然后通過setSuccessor設(shè)置了第一個處理器的下一個處理器。然后客戶端發(fā)送請求,先由第一個處理器處理,如果處理不了,再由第二個處理器處理。這樣就形成了一條處理請求的鏈條。
    • 類圖:
      image.png
  • 模型:公司購買請求決策
    公司內(nèi)有很多職位,每個職位對采購設(shè)備金額的權(quán)限都不相同,例如組長、部門長、副總、總裁等職位。小金額的組長部門可以決定,大金額的則要上報副總或總裁。

根據(jù)UML圖,我們首先要抽象出一個決策人類.這個對象抽象出處理請求的方法跟設(shè)置下一個決策人的方法
抽象決策人:

public abstract class Approver {
     Approver successor;
     String Name;
    public Approver(String Name){
        this.Name=Name;
    }
    public abstract void ProcessRequest( PurchaseRequest request);
    public void SetSuccessor(Approver successor) {
        this.successor=successor;
    }
}

組長:

public class GroupApprover extends Approver {
    public GroupApprover(String Name) {
        super(Name+" GroupLeader");     
    }
    //處理請求
    @Override
    public void ProcessRequest(PurchaseRequest request) {
        if (request.GetSum() < 5000) {//滿足一定條件才自己處理,否則交給下一個處理器
            System.out.println("**This request " + request.GetID() + " will be handled by " + this.Name + " **");
        } else {
            //交給下一個處理器
            successor.ProcessRequest(request);
        }
    }
}

部門長:

public class DepartmentApprover extends Approver {
    public DepartmentApprover(String Name) {
        super(Name + " DepartmentLeader");
    }
    @Override
    public void ProcessRequest(PurchaseRequest request) {
        if ((5000 <= request.GetSum()) && (request.GetSum() < 10000)) {
            System.out.println("**This request " + request.GetID()
                    + " will be handled by " + this.Name + " **");
        } else {
            successor.ProcessRequest(request);
        }
    }
}

副總

public class VicePresidentApprover extends Approver {
    public VicePresidentApprover(String Name) {
        super(Name + " Vice President");
    }
    @Override
    public void ProcessRequest(PurchaseRequest request) {
        if ((10000 <= request.GetSum()) && (request.GetSum() < 50000)) {
            System.out.println("**This request " + request.GetID()
                    + " will be handled by " + this.Name + " **");
        } else {
            successor.ProcessRequest(request);
        }
    }
}

總裁:

public class PresidentApprover extends Approver {
    public PresidentApprover(String Name) {
        super(Name + " President");
    }
    @Override
    public void ProcessRequest(PurchaseRequest request) {
        if (50000 <= request.GetSum()) {
            System.out.println("**This request " + request.GetID()
                    + " will be handled by " + this.Name + " **");
        }else {
            successor.ProcessRequest(request);
        }
    }
}

待處理的請求:

public class PurchaseRequest {
    private int Type = 0;
    private int Number = 0;
    private float Price = 0;
    private int ID = 0;
    public PurchaseRequest(int Type, int Number, float Price) {
        this.Type = Type;
        this.Number = Number;
        this.Price = Price;
    }
    public int GetType() {
        return Type;
    }
    public float GetSum() {
        return Number * Price;
    }
    public int GetID() {
        return (int) (Math.random() * 1000);
    }
}

客戶端發(fā)送請求:

public class Client {
    public Client() {}
    public PurchaseRequest sendRequst(int Type, int Number, float Price) {
        return new PurchaseRequest(Type, Number, Price);
    }
}

測試:

public class MainTest {
    public static void main(String[] args) {    
        Client mClient=new Client();
        Approver GroupLeader=new GroupApprover("Tom");
        Approver DepartmentLeader=new DepartmentApprover("Jerry");
        Approver VicePresident=new VicePresidentApprover("Kate");
        Approver President=new PresidentApprover("Bush");
        
        GroupLeader.SetSuccessor(VicePresident);
        DepartmentLeader.SetSuccessor(President);
        VicePresident.SetSuccessor(DepartmentLeader);
        President.SetSuccessor(GroupLeader);
        
        VicePresident.ProcessRequest(mClient.sendRequst(1, 100, 40));
        VicePresident.ProcessRequest(mClient.sendRequst(2, 200, 40));
        VicePresident.ProcessRequest(mClient.sendRequst(3, 300, 40));
        VicePresident.ProcessRequest(mClient.sendRequst(4, 400, 140));
    }
}

執(zhí)行結(jié)果:

**This request 712 will be handled by Tom GroupLeader **
**This request 589 will be handled by Jerry DepartmentLeader **
**This request 667 will be handled by Kate Vice President **
**This request 855 will be handled by Bush President **
  • 優(yōu)點:

    • 1.將請求的發(fā)送者與接收者解耦,使多個對象都有機會處理。
    • 2.簡化處理器對象的結(jié)構(gòu),無需知道鏈的關(guān)系。
    • 3.可以動態(tài)的增刪處理請求鏈結(jié)構(gòu)。也可以指定從任意處理器開始處理。
  • 對比狀態(tài)模式、策略模式:
    從UML類圖看,這三種模式很是相近,容易使人混淆。前面的狀態(tài)模式中已經(jīng)對比了狀態(tài)模式與策略模式,這里對比下狀態(tài)與責任鏈模式:
    狀態(tài)模式:是讓各個狀態(tài)對象自己知道其下一個處理的對象是誰,即在編譯時便設(shè)定。設(shè)計思路是把邏輯判斷轉(zhuǎn)移到各個State類的內(nèi)部,執(zhí)行時客戶端通過調(diào)用環(huán)境—Context類的方法來間接執(zhí)行狀態(tài)類的行為,客戶端不直接和狀態(tài)交互。
    職責鏈模式:各個對象并不指定其下一個處理的對象到底是誰,而是在客戶端設(shè)定某個類型的鏈條,請求發(fā)出后穿越鏈條,直到被某個職責類處理或者鏈條結(jié)束。設(shè)計思路是把各個業(yè)務邏輯判斷封裝到不同職責類,且攜帶下一個職責的對應引用,但不像狀態(tài)模式那樣需要明確知道這個引用指向誰,而是在環(huán)境類設(shè)置鏈接方式或者過程。使用時,向鏈的第一個子類的執(zhí)行方法傳遞參數(shù)就可以??蛻舳巳ネㄟ^環(huán)境類調(diào)用責任鏈,全自動運轉(zhuǎn)起來。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 場景問題# 1.1 申請聚餐費用## 來考慮這樣一個功能:申請聚餐費用的管理。 很多公司都有這樣的福利,就是項...
    七寸知架構(gòu)閱讀 3,275評論 3 58
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是責任鏈模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 純與不純的責任鏈模式 優(yōu)點和缺點 ...
    w1992wishes閱讀 1,321評論 4 14
  • 前言 Android的設(shè)計模式系列文章介紹,歡迎關(guān)注,持續(xù)更新中: Android的設(shè)計模式-設(shè)計模式的六大原則一...
    四月葡萄閱讀 10,058評論 5 20
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 春天清晨的風掠過發(fā)梢?guī)е瞧鷻C 悄聲告訴你打破了冬的寧靜 它來了春風如你 十里送暖夏天午夜的月光穿透樹葉映照在地...
    南墻佳人閱讀 311評論 0 0

友情鏈接更多精彩內(nèi)容