(46)C#設計模式—— 責任鏈模式

引言

在現實生活中,有很多請求並不是一個人說了算,例如面試時的工資,地獄1萬的可能技術經理就可以決定了,但是1萬到1萬5的公司可能技術經理就沒這個權利批准,可能就需要請求技術總監的批准,所以面試的話,經常會有面試者說,你這個薪水我覺得你這技術可以拿這個薪水的,但是還需要技術總監的批准等話。這個例子引出了我們要介紹的責任鏈模式。

定義

從生活中的例子可以看出,某個請求需要幾個人的審批,即使技術經理審批完了,還需要上一級的審批。這樣的例子,還有公司的請假,根據不同時長的請假要求,可能需要不同的人來審覈。

責任鏈模式指的是某個請求需要多個對象處理,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一條鏈子,並沿着這條鏈子傳遞請求,知道有對象處理它爲止。

角色

責任鏈模式涉及到的角色有:

  • 抽象處理角色:定義一個處理請求的接口,這個接口通常由接口或者抽象類來實現。
  • 具體處理者角色:具體處理者接收到請求後,可以選擇將該請求處理掉,或者將請求傳遞給下一個處理者。因此,每個具體處理者需要保存下一個處理者的引用,方便把請求傳遞下去。

實現

以公司採購東西的例子來說明如何實現責任鏈模式。公司規定,採購價格總價在1萬之內,經理級別的人批准即可。總價大於1萬小於2萬5的則還需要副總進行批准,總價大於2萬5小於10萬的還需要總經理的批准,而總價大於10萬的則需要組織會議進行討論。對於這樣的一個需求,最直觀的方法就是設計一個方法,參數是採購的總價,然後在這個方法內對價格進行調整判斷,然後針對不同的條件交給不同級別的人去處理,這樣確實可以解決問題。但是這樣設計,我們就需要使用多重if-else語句來進行判斷,當加入一個新的條件範圍時,我們不得不去修改原來設計的方法,不易於擴展。利用責任鏈模式可以解決這樣的問題。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _37ZeRenLianPatternDemo
{
    //採購請求
    public class PurchaseRequest
    {
        //金額
        public double Amount { get; set; }
        //產品名字
        public string ProductName { get; set; }
        public PurchaseRequest(double amount, string productName)
        {
            Amount = amount;
            ProductName = productName;
        }
    }
    //審批人
    public abstract class Approver
    {
        public Approver NextApprover { get; set; }
        public string Name { get; set; }
        public Approver(string name)
        {
            this.Name = name;
        }
        public abstract void ProcessRequest(PurchaseRequest request);
    }
    //具體審批者
    public class Manager : Approver
    {
        public Manager(string name) : base(name)
        {
        }
        public override void ProcessRequest(PurchaseRequest request)
        {
            if(request.Amount<10000.0)
            {
                Console.WriteLine("{0}-{1} approved the request of purshing{2}", this, Name, request.ProductName);
            }
            else
            {
                NextApprover.ProcessRequest(request);
            }
        }
    }
    public class VicePresident : Approver
    {
        public VicePresident(string name) : base(name)
        {
        }

        public override void ProcessRequest(PurchaseRequest request)
        {
            if (request.Amount < 25000.00)
            {
                Console.WriteLine("{0}-{1} approved the request of purshing{2}", this, Name, request.ProductName);
            }
            else if (NextApprover != null)
            {
                NextApprover.ProcessRequest(request);
            }
        }
    }
    public class President : Approver
    {
        public President(string name) : base(name)
        {
        }

        public override void ProcessRequest(PurchaseRequest request)
        {
            if (request.Amount < 100000.00)
            {
                Console.WriteLine("{0}-{1} approved the request of purshing{2}", this, Name, request.ProductName);
            }
            else
            {
                Console.WriteLine("Request需要組織會議");
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PurchaseRequest requestPhone = new PurchaseRequest(4000.00, "Phone");
            PurchaseRequest requestComputer = new PurchaseRequest(10000.00, "Computer");
            PurchaseRequest requestAircontiditon = new PurchaseRequest(40000.0, "Aircondition");
            PurchaseRequest request = new PurchaseRequest(200000.00, "Car");

            Approver manager = new Manager("Tom");
            Approver VicePresident = new VicePresident("Bob");
            Approver President = new President("James");

            //設置責任鏈
            manager.NextApprover = VicePresident;
            VicePresident.NextApprover = President;
            //處理請求
            manager.ProcessRequest(requestPhone);
            manager.ProcessRequest(requestComputer);
            manager.ProcessRequest(requestAircontiditon);
            manager.ProcessRequest(request);

        }
    }
}

使用場景

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

優缺點

優點

  • 降低了請求的發送者和接收者之間的耦合
  • 把多個條件判定分散到各個處理類中,使得代碼更清晰,責任更明確

缺點

  • 在找到正確的處理對象之前,所有的條件判定都要執行一遍,當責任鏈過長時,可能會引起性能的問題
  • 可能導致某個請求不被處理

總結

責任鏈降低了請求端和接收端之間的耦合,使多個對象都有機會處理某個請求。 如考試中作弊傳紙條,拍拖傳情書一般。可能直接傳到目的地,也可能中間經過多次傳遞

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