問題抽象
客戶端發出一個請求,會有很多對象都可以來處理這個請求,而且不同對象的處理邏輯是不一樣的。
對於客戶端而言,無所謂誰來處理,反正有對象處理就可以了。而且在上述處理中,還希望處理流程是可以靈活變動的,而處理請求的對象需要能方便地修改或者是被替換掉,以適應新的業務功能的需要。
職責鏈模式
十多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這個對象連城一條鏈,並沿着這條鏈傳遞該請求,知道有一個對象處理它爲止。
模式結構
-
抽象處理者(Handler)角色
定義出一個處理請求的接口。如果需要,接口可以定義出一個方法以設定和返回對下家的引用。這個角色通常由一個抽象類或接口實現。 -
具體處理者(ConcreteHandler)角色
具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者司以訪問下家。
處理過程
ConcreteHandler將自己的後繼對象(向下傳遞消息的對象)記錄在自己的後繼表中,當一個請求到來時,ConcreteHandler會先檢查看自己有沒有匹配的處理程序,如果有就自己處理,否則傳遞給它的後繼。
職責鏈模式降低了請求的發送端和接收端之間的耦合,使多個對象都有機會處理這個請求。
優點
請求者和接收者鬆散耦合
動態組合職責
缺點
產生很多細粒度對象
不一定能被處理:需要提供默認處理
本質
分離職責,動態組合,如果學習過狀態模式,可以理解爲可以動態設置轉移方向的狀態模式。
狀態模式是一個對象的內在狀態發生改變,一個對象,相對比較穩定,處理完一個對象下一個對象的處理一般都已確定
職責鏈模式過於靈話,在客戶端使用時,需要環境去確定下一個對象是誰,一些列的set操作…職責鏈模式是多個對象之間的改變,就會出現某個對象不存在的情景。
實現:
我們使用百度百科的一個例子:
//申請
public class Request
{
//申請類別
private string requestType;
public String getrequestType (){
return requestType;
}
public void setrequestType (string requestType){
this.requestType=requestType;
}
//申請內容
private string requestContent;
public String getrequestContent (){
return requestContent;
}
public void setrequestContent (string requestContent){
this.requestContent=requestContent;
}
//數量
private int number;
public int Number
{
get { return number; }
set { number = value; }
}
}
//管理者--Handler類,定義一個處理請求的接口
abstract public class Manager
{
protected string name;
//管理者上級
protected Manager superior;
public Manager(string name)
{
this.name = name;
}
//設置管理者上級---關鍵的方法
public void SetSuperior(Manager superior)
{
this.superior = superior;
}
abstract public void RequestApplications(Request request);
}
//"經理類"就可以去繼承這個"管理者"類,只需要重寫"申請請求"的方法就可以
//經理類
public class CommonManager extends Manager
{
public CommonManager(string name) { super(name);}
publicvoid RequestApplications(Request request)
{
//經理的權限可批准下屬兩天內的請假
if (request.RequestType == "請假" && request.Number <= 2)
{
Console.WriteLine("{0}:{1}數量{2}被批准", name, request.RequestContent, request.Number);
}
else
{
//其他的申請都要轉到上級
if (superior != null)
superior.RequestApplications(request);
}
}
}
//"總監類"同樣繼承這個"管理者"類
//總監類
public class Majordomo extends Manager
{
public Majordomo(string name) { super(name);}
public void RequestApplications(Request request)
{
//總監的權限可批准下屬五天內的請假
if (request.RequestType == "請假" && request.Number <= 5)
{
System.out.println( name+":"+ request.RequestContent+"數量"+request.Number+"被批准");
}
else
{
//其他的申請都要轉到上級
if (superior != null)
superior.RequestApplications(request);
}
}
}
//"總經理"的權限就是全部處理
//總監類
public class GeneralManager extends Manager
{
public GeneralManager(string name) {super(name); }
publicvoid RequestApplications(Request request)
{
//總經理的權限可批准下屬任意天數的請假
if (request.RequestType == "請假")
{
System.out.println( name+":"+ request.RequestContent+"數量"+request.Number+"被批准");
}
else if (request.RequestType == "加薪"&&request.Number<=500)
{
System.out.println( name+":"+ request.RequestContent+"數量"+request.Number+"被批准");
}
else if (request.RequestType == "加薪" && request.Number > 500)
{
System.out.println( name+":"+ request.RequestContent+"數量"+request.Number+"在說吧");
}
}
}
public class Client
{
//客戶端代碼
public static void Main(string[] args)
{
CommonManager jinli = new CommonManager("張三");
Majordomo zongjian = new Majordomo("李四");
GeneralManager zongjinli = new GeneralManager("王五");
//設置上級
jinli.SetSuperior(zongjian);
zongjian.SetSuperior(zongjinli);
Request request = new Request();
request.RequestType = "請假";
request.RequestContent = "XX請假";
request.Number = 1;
jinli.RequestApplications(request);
Request request2 = new Request();
request.RequestType = "加薪";
request.RequestContent = "XX加薪";
request.Number = 500;
jinli.RequestApplications(request);
}
}