原理或定義
是一種對象的行爲模式。在職責鏈模式裏,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。
結構
抽象處理者(Handler)角色:定義出一個處理請求的接口。如果需要,接口可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類或接口實現。
具體處理者(ConcreteHandle)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。;
類圖
案例與代碼
本文使用購買請求決策項目作爲示例
購買請求決策項目介紹
決策因素:價格
決策級別:組長、部長、副總、總裁
一般設計方案:
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);
}
public void ProcessRequest(){
if(GetSum>500){
System.out.println("**This request " + request.GetID()
+ " will be handled by Group **");
}else if(){
System.out.println("**This request " + request.GetID()
+ " will be handled by Department **");
}else if(){
....
}
}
}
public class MainTest {
public static void main(String[] args) {
PurchaseRequest request=new PurchaseRequest(1, 100, 40);
request.ProcessRequest();
}
}
通過if else 語句判斷級別。
這樣設計會破壞開閉原則,還會導致強耦合。
責任鏈模式設計方案:
類圖:
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);
}
}
抽象處理者(Handler)角色:
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) {
// TODO Auto-generated method stub
this.successor=successor;
}
}
具體處理者(ConcreteHandle)角色:
public class GroupApprover extends Approver {
public GroupApprover(String Name) {
super(Name+" GroupLeader");
// TODO Auto-generated constructor stub
}
@Override
public void ProcessRequest(PurchaseRequest request) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated method stub
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 PresidentApprover extends Approver {
public PresidentApprover(String Name) {
super(Name + " President");
}
@Override
public void ProcessRequest(PurchaseRequest request) {
// TODO Auto-generated method stub
if (50000 <= request.GetSum()) {
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) {
// TODO Auto-generated method stub
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 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));
}
}
如果有多個對象都有機會處理請求,責任鏈可使請求的發送者和接收者解耦,請求沿着責任鏈傳遞,直到有一個對象處理了它爲止。
使用場景
1.多個對象可以處理同一請求,但具體由哪個對象處理則在運行時動態決定;
2.在請求處理着不明確的情況下向多個對象的一個提交一個請求;
3.需要動態指定一組對象處理請求
優缺點
主要優點有:
1. 請求者與處理者代碼分離:降低了耦合度。
2.將請求的發送者和接收者解耦,使多個對象都有機會處理這個請求
3.可以簡化對象,因爲它無須知道鏈的結構
4.可以動態地增加或刪減處理請求的鏈結構
缺點主要有:
責任鏈像一條鏈表一樣,效率可能會有問題。不能保證請求一定被收到。