1. 程式人生 > >【C#設計模式-責任鏈模式】

【C#設計模式-責任鏈模式】

一.責任鏈模式的定義:

責任鏈模式指的是——某個請求需要多個物件進行處理,從而避免請求的傳送者和接收之間的耦合關係。將這些物件連成一條鏈子,並沿著這條鏈子傳遞該請求,直到有物件處理它為止。

二.責任鏈模式的結構和角色:

抽象處理者(Handler)角色:

定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。

具體處理者(ConcreteHandler)角色:

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

三.責任鏈模式的實現:

在生活中,公司部門舉辦活動需要申請金費,如果金費<=1000,部門經理就可以批准發放,如果金額超過1000而<=5000,部門經理無權力批准,副總經理可以批准發放,如果金額超過5000而<=10000,副總經理沒有權力批准,此時只有總經理可以批准,而超過10000,就要就行會議決定。對於這樣的需求,每個角色的責任是不一樣的,如果使用傳統的方式,可能是寫個if多條件判斷,可以滿足現有的需要,但是後面增加新的角色賦予責任,就需要改變if結構判斷,違背設計原則中的對擴充套件開發,對修改關閉原則。使用責任鏈模式可以很方便的擴充套件。

    /// <summary>
    /// 行為請求
    /// </summary>
    public class BehaviourRequest
    {
        /// <summary>
        /// 金額
        /// </summary>
        public double Money { get; set; }

        /// <summary>
        /// 活動名稱
        /// </summary>
        public string ActiveName { get; set; }

        public BehaviourRequest(double money, string activename) 
        {
            this.Money = money;
            this.ActiveName = activename;
        }
    }
    /// <summary>
    /// 角色抽象類
    /// </summary>
    public abstract class RoleAbstract
    {
        public RoleAbstract NextRole { get; set; }
        public string name { get; set; }
        public RoleAbstract(string name)
        { this.name = name; }

        /// <summary>
        /// 該角色的執行行為
        /// </summary>
        public abstract void Behaviour(BehaviourRequest request);
    }
    /// <summary>
    /// 部門經理
    /// </summary>
    public class ManagerRole:RoleAbstract
    {
        public ManagerRole(string name) : base(name) { }

        public override void Behaviour(BehaviourRequest request)
        {
            if (request.Money <= 1000)
            {
                Console.WriteLine("{0}的請求批准得到{1}批准,需要金額:{2}", request.ActiveName,this.name, request.Money);
            }
            else if (NextRole != null)
            {
                Console.WriteLine("{0}無權力批准,給上級{0}處理!", this.name, NextRole.name);
                NextRole.Behaviour(request);
            }
        }
    }
    /// <summary>
    /// 副總經理角色
    /// </summary>
    public class PresidentRole:RoleAbstract
    {
        public PresidentRole(string name) : base(name) { }

        public override void Behaviour(BehaviourRequest request)
        {
            if (request.Money <= 5000) 
            {
                Console.WriteLine("{0}的請求批准得到{1}批准,需要金額:{2}", request.ActiveName, this.name, request.Money);
            }
            else if (NextRole != null)
            {
                Console.WriteLine("{0}無權力批准,給上級{0}處理!", this.name, NextRole.name);
                NextRole.Behaviour(request);
            }
        }
    }
    /// <summary>
    /// 總經理
    /// </summary>
    public class PresidengtRole:RoleAbstract
    {
        public PresidengtRole(string name) : base(name) { }

        public override void Behaviour(BehaviourRequest request)
        {
            if (request.Money <= 10000)
            {
                Console.WriteLine("{0}的請求批准得到{1}批准,需要金額:{2}", request.ActiveName, this.name, request.Money);
            }
            else 
            {
                Console.WriteLine("這個活動需要進行會議討論決定");
            }
        }
    }
    /// <summary>
    /// C#設計模式-責任鏈模式
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            //活動資訊
            BehaviourRequest behavior = new BehaviourRequest(10000, "部門招商活動");
            
            //對該活動的審批可能涉及的角色
            RoleAbstract manager = new ManagerRole("部門經理");
            RoleAbstract vp = new PresidentRole("副總經理");
            RoleAbstract pre = new PresidengtRole("總經理");

            //設定責任鏈
            manager.NextRole = vp;
            vp.NextRole = pre;

            //請求處理
            manager.Behaviour(behavior);
        }
    }



執行結果:

在進行10000元活動的審批過程中,首先通過部門經理,轉交給副總經理,然後再到總經理,根據每個角色的責任進行判斷,當無許可權批准某一行為請求的時候,就交個上一級進行處理。

四.責任鏈模式的適用場景:

一個系統的審批需要多個物件才能完成處理的情況下,例如請假系統等。
程式碼中存在多個if-else語句的情況下,此時可以考慮使用責任鏈模式來對程式碼進行重構。

五.責任鏈模式的優缺點:

優點:
降低了請求的傳送者和接收者之間的耦合。
把多個條件判定分散到各個處理類中,使得程式碼更加清晰,責任更加明確。
缺點:
在找到正確的處理物件之前,所有的條件判定都要執行一遍,當責任鏈過長時,可能會引起效能的問題
可能導致某個請求不被處理。