定義:
在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發(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)起來。

