<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # C#設計模式(21)——責任鏈模式 ## 一、引言 在現實生活中,有很多請求并不是一個人說了就算的,例如面試時的工資,低于1萬的薪水可能技術經理就可以決定了,但是1萬~1萬5的薪水可能技術經理就沒這個權利批準,可能就需要請求技術總監的批準,所以在面試的完后,經常會有面試官說,你這個薪水我這邊覺得你這技術可以拿這個薪水的,但是還需要技術總監的批準等的話。這個例子也就詮釋了本文要介紹的內容。生活中的這個例子真是應用了責任鏈模式。 ## 二、責任鏈模式介紹 ## 2.1 責任鏈模式的定義 從生活中的例子可以發現,某個請求可能需要幾個人的審批,即使技術經理審批完了,還需要上一級的審批。這樣的例子,還有公司中的請假,少于3天的,直屬Leader就可以批準,3天到7天之內就需要項目經理批準,多余7天的就需要技術總監的批準了。介紹了這么多生活中責任鏈模式的例子的,下面具體給出面向對象中責任鏈模式的定義。 責任鏈模式指的是——某個請求需要多個對象進行處理,從而避免請求的發送者和接收之間的耦合關系。將這些對象連成一條鏈子,并沿著這條鏈子傳遞該請求,直到有對象處理它為止。 ## 2.2 責任鏈模式的結構圖 從責任鏈模式的定義可以發現,責任鏈模式涉及的對象只有處理者角色,但由于有多個處理者,它們具有共同的處理請求的方法,所以這里抽象出一個抽象處理者角色進行代碼復用。這樣分析下來,責任鏈模式的結構圖也就不言而喻了,具體結構圖如下所示。 ![](https://box.kancloud.cn/2016-01-23_56a2eb3e77889.png) 主要涉及兩個角色: * 抽象處理者角色(Handler):定義出一個處理請求的接口。這個接口通常由接口或抽象類來實現。 * 具體處理者角色(ConcreteHandler):具體處理者接受到請求后,可以選擇將該請求處理掉,或者將請求傳給下一個處理者。因此,每個具體處理者需要保存下一個處理者的引用,以便把請求傳遞下去。 ## 2.3 責任鏈模式的實現 有了上面的介紹,下面以公司采購東西為例子來實現責任鏈模式。公司規定,采購架構總價在1萬之內,經理級別的人批準即可,總價大于1萬小于2萬5的則還需要副總進行批準,總價大于2萬5小于10萬的需要還需要總經理批準,而大于總價大于10萬的則需要組織一個會議進行討論。對于這樣一個需求,最直觀的方法就是設計一個方法,參數是采購的總價,然后在這個方法內對價格進行調整判斷,然后針對不同的條件交給不同級別的人去處理,這樣確實可以解決問題,但這樣一來,我們就需要多重if-else語句來進行判斷,但當加入一個新的條件范圍時,我們又不得不去修改原來設計的方法來再添加一個條件判斷,這樣的設計顯然違背了“開-閉”原則。這時候,可以采用責任鏈模式來解決這樣的問題。具體實現代碼如下所示。 ``` namespace ChainofResponsibility { // 采購請求 public class PurchaseRequest { // 金額 public double Amount { get; set; } // 產品名字 public string ProductName { get; set; } public PurchaseRequest(double amount, string productName) { Amount = amount; ProductName = productName; } } // 審批人,Handler 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); } // ConcreteHandler 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 if (NextApprover != null) { NextApprover.ProcessRequest(request); } } } // ConcreteHandler,副總 public class VicePresident : Approver { public VicePresident(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 25000.0) { Console.WriteLine("{0}-{1} approved the request of purshing {2}", this, Name, request.ProductName); } else if (NextApprover != null) { NextApprover.ProcessRequest(request); } } } // ConcreteHandler,總經理 public class President :Approver { public President(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 100000.0) { 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 requestTelphone = new PurchaseRequest(4000.0, "Telphone"); PurchaseRequest requestSoftware = new PurchaseRequest(10000.0, "Visual Studio"); PurchaseRequest requestComputers = new PurchaseRequest(40000.0, "Computers"); Approver manager = new Manager("LearningHard"); Approver Vp = new VicePresident("Tony"); Approver Pre = new President("BossTom"); // 設置責任鏈 manager.NextApprover = Vp; Vp.NextApprover = Pre; // 處理請求 manager.ProcessRequest(requestTelphone); manager.ProcessRequest(requestSoftware); manager.ProcessRequest(requestComputers); Console.ReadLine(); } } } ``` 既然,原來的設計會因為價格條件范圍的變化而導致不利于擴展,根據“封裝變化”的原則,此時我們想的自然是能不能把價格范圍細化到不同的類中呢?因為每個價格范圍都決定某個批準者,這里就聯想到創建多個批準類,這樣每個類中只需要針對他自己這個范圍的價格判斷。這樣也就是責任鏈的最后實現方式了,具體的運行結果如下圖所示。 ![](https://box.kancloud.cn/2016-01-23_56a2eb3e83d1b.png) ## 三、責任鏈模式的適用場景 在以下場景中可以考慮使用責任鏈模式: * 一個系統的審批需要多個對象才能完成處理的情況下,例如請假系統等。 * 代碼中存在多個if-else語句的情況下,此時可以考慮使用責任鏈模式來對代碼進行重構。 ## 四、責任鏈模式的優缺點 責任鏈模式的優點不言而喻,主要有以下點: * 降低了請求的發送者和接收者之間的耦合。 * 把多個條件判定分散到各個處理類中,使得代碼更加清晰,責任更加明確。 責任鏈模式也具有一定的缺點,如: * 在找到正確的處理對象之前,所有的條件判定都要執行一遍,當責任鏈過長時,可能會引起性能的問題 * 可能導致某個請求不被處理。 ## 五、總結 責任鏈降低了請求端和接收端之間的耦合,使多個對象都有機會處理某個請求。如考試中作弊傳紙條,泡妞傳情書一般。在下一章將繼續分享訪問者模式。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看