C#設計模式系列:職責鏈模式(Chain of Responsibility)

libingql發表於2014-04-07

1、職責鏈模式簡介

1.1>、定義

  職責鏈模式是一種行為模式,為解除請求的傳送者和接收者之間的耦合,而使多個物件都有機會處理這個請求。將這些物件連線成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它。

1.2>、使用頻率

   中低

2、職責鏈模式結構

2.1>、結構圖

2.2>、參與者

  職責鏈模式參與者:

  ◊ Handler

    ° 定義一個處理請求的介面

    ° 實現後繼鏈

  ◊ ConcreteHandler

    ° 處理其所負責的請求

    ° 可訪問其後繼者

    ° 如果可處理該請求,則處理;否則將該請求轉發給它的後繼者。

  ◊ Client:向鏈上的具體處理者物件提交請求

  在職責鏈模式中,Client向Handler提交請求,請求在多個ConcreteHandler物件形成的物件鏈中被傳遞,請求在傳遞的過程中被處理。

3、職責鏈模式結構實現

  Handler.cs

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

namespace DesignPatterns.ChainOfResponsibilityPattern.Structural
{
    public abstract class Handler
    {
        protected Handler successor;

        public void SetSuccessor(Handler successor)
        {
            this.successor = successor;
        }

        public abstract void HandleRequest(int request);
    }
}

  ConcreteHandler1.cs

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

namespace DesignPatterns.ChainOfResponsibilityPattern.Structural
{
    public class ConcreteHandler1 : Handler
    {
        public override void HandleRequest(int request)
        {
            if (request >= 0 && request < 10)
            {
                Console.WriteLine("{0} handled request {1}", this.GetType().Name, request);
            }

            else if (successor != null)
            {
                successor.HandleRequest(request);
            }
        }
    }
}

  ConcreteHandler2.cs

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

namespace DesignPatterns.ChainOfResponsibilityPattern.Structural
{
    public class ConcreteHandler2 : Handler
    {
        public override void HandleRequest(int request)
        {
            if (request >= 10 && request < 20)
            {
                Console.WriteLine("{0} handled request {1}", this.GetType().Name, request);
            }

            else if (successor != null)
            {
                successor.HandleRequest(request);
            }
        }
    }
}

  ConcreteHandler3.cs

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

namespace DesignPatterns.ChainOfResponsibilityPattern.Structural
{
    public class ConcreteHandler3 : Handler
    {
        public override void HandleRequest(int request)
        {
            if (request >= 20 && request < 30)
            {
                Console.WriteLine("{0} handled request {1}", this.GetType().Name, request);
            }

            else if (successor != null)
            {
                successor.HandleRequest(request);
            }
        }
    }
}

  Program.cs

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

using DesignPatterns.ChainOfResponsibilityPattern.Structural;

namespace DesignPatterns.ChainOfResponsibilityPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Setup Chain of Responsibility
            Handler h1 = new ConcreteHandler1();
            Handler h2 = new ConcreteHandler2();
            Handler h3 = new ConcreteHandler3();

            h1.SetSuccessor(h2);
            h2.SetSuccessor(h3);

            // Generate and process request
            int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };

            foreach (int request in requests)
            {
                h1.HandleRequest(request);
            }
        }
    }
}

  執行輸出:

ConcreteHandler1 handled request 2
ConcreteHandler1 handled request 5
ConcreteHandler2 handled request 14
ConcreteHandler3 handled request 22
ConcreteHandler2 handled request 18
ConcreteHandler1 handled request 3
ConcreteHandler3 handled request 27
ConcreteHandler3 handled request 20
請按任意鍵繼續. . .

  上例中,ConcreteHandler1負責處理的請求範圍0~10,ConcreteHandler2負責處理的請求範圍10~20,ConcreteHandler3負責處理的請求範圍20~30。當請求ConcreteHandler1處理不了,則讓ConcreteHandler2處理,如果ConcreteHandler2處理不了,則讓ConcreteHandler3處理。依次類推,Client的請求會驗證職責鏈傳遞下去,直至請求被處理,而Client不要關心到底是誰處理了請求。

4、職責鏈模式應用分析

  職責鏈模式適用情形:

  1>、可能處理請求的物件集合以及它們在連結串列中的順序是由Client根據當前應用的狀態在執行時動態決定的;

  2>、Client根據狀態,對於不同的請求型別,可以擁有不同的可能處理請求的物件集合。一個處理請求的物件也可以根據Client的狀態和請求型別,把請求傳遞給不同的處理物件。

  3>、Client初始化請求,或者在不知道這些物件是否能處理這個請求的情況下初始化任何可能處理請求的物件。Client和在處理連結串列中的處理物件都不需要知道到底哪個物件去處理這個請求。

  4>、請求不能保證被處理。在沒有處理的情況下,請求已經到達了處理鏈的表尾。

  職責鏈模式特點:

  1>、職責鏈模式降低了發出命令的物件和處理命令的物件之間的耦合,它允許多於一個的處理者物件根據自己的邏輯來決定哪個處理者最終處理這個命令。發出命令的物件只是把命令傳給鏈結構的起始者,而不需要知道到底是鏈上的哪一個節點處理了這個命令。這樣在處理命令上,允許系統由更多的靈活性。哪一個物件最終處理一個命令可以由那些物件參加職責鏈,以及隨著這些物件在職責鏈上的位置不同而不同。

  2>、既然一個請求沒有明確的接收者,那麼就不能保證它一定會被處理。該請求可能一直到鏈的末端都得不到處理。一個請求也可以因該鏈沒有被正確配置而得不到響應,並且處理訊息傳遞和處理不當會出現訊息的迴圈重複執行。

相關文章