C#設計模式之職責鏈模式

提高班14期郭倩_Ulrica發表於2018-06-08

職責鏈模式

使多個物件都有機會處理請求,從而避免請求的傳送者和接收者之間的耦合關係。將這個物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止。
這樣就解決了違背單一職責原則了。

場景

很像公司的管理,如果我是一個公司的應聘者,我想要加薪,如果我的上級能通過這個加薪請求,就可以自行解決,如果面額太大,他不能隨便做主,或者不在他的管理範圍內,這個時候,就要向再上一級反應,直到這個請求能夠達到能處理的人的手裡。
聽起來有些像職責大小的味道。
加薪

好處

當客戶提交一個請求時,請求時沿職責鏈傳遞直至有一個具體處理者類物件負責處理它。也就是說請求者不用管時誰處理的,只要能被處理就可以了。
這樣接收者和傳送者都沒有對方的明確資訊,且鏈中的物件自己也並不知道鏈的結構,結果時職責鏈可簡化物件的相互連線,它們僅需保持一個指向其後繼者(上司)的引用,而不需保持它所有的候選接收者的引用。這就大大的降低了耦合度。

不過要注意的一點是:

一個請求極有可能到了鏈的末端都得不到處理,或者因為沒有正確配置而得不到處理,這就糟糕了,所以考慮時要全面一些。

example:

  1. 我要給你發一封郵件,但是郵箱地址寫錯了,這個時候,不管怎樣遞推,最終都到不了你的郵箱。

所以最重要的有兩點:

  1. 要事先給每個具體管理者設定它的上司!也就是設定後繼者。
  2. 在每個具體管理者處理請求時,做出判斷,是否可以處理這個請求,如果不能,則”推卸責任“交給後繼者去處理。-

程式碼展示

申請–返回值

//申請
    class Request
    {
        //申請類別
        private string requestType;
        public string RequestType
        {
            get { return requestType; }
            set { requestType = value; }
        }

        //申請內容
        private string requestContent;
        public string RequestContent
        {
            get { return requestContent; }
            set { requestContent = value; }
        }

        //數量
        private int number;
        public int Number
        {
            get { return number; }
            set { number = value; }
        }
    }

管理者類:

abstract 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);
    }

具體管理者類:

//經理類
    class CommonManager:Manager 
    {
        public CommonManager(string name)
            : base(name)
        { }

        public override void 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);
            }
        }
    }



//總監類----------------程式碼同經理類,許可權大一些。
    class Majordomo:Manager 
    {
        public Majordomo(string name)
            : base(name)
        { }

        public override void RequestApplications(Request request)
        {
            //總監所能有的許可權就是可准許下屬5天內的假期

            if (request.RequestType == "請假" && request.Number <= 5)
            {
                Console.WriteLine("{0}:{1} 數量{2} 被批准",name,request .RequestContent ,request .Number );
            }
            else 
            {
                //其餘申請都轉到上級,我辦不了
                if (superior != null)
                    superior.RequestApplications(request);
            }
        }




//總經理類---------------------程式碼和經理,總監類似,擁有職權更大
    class GeneralManager:Manager 
    {
        public GeneralManager(string name)
            : base(name)
        { }

        public override void RequestApplications(Request request)
        {
            //總經理所能有的許可權就是全部需要處理

            if (request.RequestType == "請假" )//&& request.Number <= 2)可准許任意天數的假期
            {
                Console.WriteLine("{0}:{1} 數量{2} 被批准",name, request .RequestContent ,request .Number );
            }
            else if(request .RequestType =="加薪"&&request .Number <=10000 )
            {
                Console.WriteLine("{0}:{1} 數量{2} 被批准", name, request.RequestContent, request.Number);
            }
            else if(request .RequestType =="加薪" &&request .Number >10000)
            {
                Console.WriteLine("{0}:{1} 數量{2} 哈哈。做你的春秋大夢吧~", name,request.RequestContent, request.Number);
            }

        }
    }

客戶端程式碼:

class Program
    {
        static void Main(string[] args)
        {
            CommonManager jingli = new CommonManager("天");//設定經理
            Majordomo zongjian = new Majordomo("地");//設定總監
            GeneralManager zongjingli = new GeneralManager("猴子");//設定總經理
            jingli.SetSuperior(zongjian);//職責傳遞
            zongjian.SetSuperior(zongjingli);

//請求1
            Request request = new Request();
            request.RequestType = "請假";
            request.RequestContent = "小郭請假";
            request.Number = 4;
            jingli.RequestApplications(request);
//請求2
            Request request1 = new Request();
            request1.RequestType = "請假";
            request1.RequestContent = "小郭請假";
            request1.Number = 500;
            jingli.RequestApplications(request1);
//類似
            Request request2 = new Request();
            request2.RequestType = "加薪";
            request2.RequestContent = "小郭要加薪";
            request2.Number = 9999;
            jingli.RequestApplications(request2);
//類似
            Request request3 = new Request();
            request3.RequestType = "加薪";
            request3.RequestContent = "小郭要加薪";
            request3.Number = 2000000000;
            jingli.RequestApplications(request3);

            Console.Read();

        }
    }

後記

看來加薪也不是說加就能加的哦~

相關文章