『設計模式』職責鏈模式(Chain of Responsibility) 可憐的加薪、請假之路

問題抽象

客戶端發出一個請求,會有很多對象都可以來處理這個請求,而且不同對象的處理邏輯是不一樣的。
對於客戶端而言,無所謂誰來處理,反正有對象處理就可以了。而且在上述處理中,還希望處理流程是可以靈活變動的,而處理請求的對象需要能方便地修改或者是被替換掉,以適應新的業務功能的需要。

職責鏈模式

十多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這個對象連城一條鏈,並沿着這條鏈傳遞該請求,知道有一個對象處理它爲止。

模式結構

在這裏插入圖片描述

  • 抽象處理者(Handler)角色
    定義出一個處理請求的接口。如果需要,接口可以定義出一個方法以設定和返回對下家的引用。這個角色通常由一個抽象類或接口實現。

  • 具體處理者(ConcreteHandler)角色
    具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者司以訪問下家。

處理過程

ConcreteHandler將自己的後繼對象(向下傳遞消息的對象)記錄在自己的後繼表中,當一個請求到來時,ConcreteHandler會先檢查看自己有沒有匹配的處理程序,如果有就自己處理,否則傳遞給它的後繼。

職責鏈模式降低了請求的發送端和接收端之間的耦合,使多個對象都有機會處理這個請求。

優點

請求者和接收者鬆散耦合
動態組合職責

缺點

產生很多細粒度對象
不一定能被處理:需要提供默認處理

本質

分離職責,動態組合,如果學習過狀態模式,可以理解爲可以動態設置轉移方向的狀態模式。

vv

狀態模式是一個對象的內在狀態發生改變,一個對象,相對比較穩定,處理完一個對象下一個對象的處理一般都已確定
職責鏈模式過於靈話,在客戶端使用時,需要環境去確定下一個對象是誰,一些列的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);

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章