責任鏈模式介紹

責任鏈模式是一種行為設計模式,允許你將請求沿着處理者鏈進行發送。收到請求后,每個處理者均可對請求進行處理,或將其傳遞給鏈上的下個處理者。
責任鏈模式的核心是解決一組服務中的先后執行處理關系。
責任鏈模式可以讓各個服務模塊更加清晰,而每一個模塊可以通過next的方式進行獲取。而每一個next是由繼承的統一抽象類實現的,最終所有類的職責可以動態的進行編排使用,編排的過程可以做成可配置化。
在使用責任鏈時,如果場景比較固定,可寫死到代碼中進行初始化。但如果業務場景經常變化可以做成xml配置的方式進行處理,也可以保存到數據庫中進行初始化操作。
實際的業務中在使用責任鏈時會進行一系列的包裝,通過把不同的責任節點進行組裝,構成一條完整業務的責任鏈。
責任鏈模式很好的處理單一職責和開閉原則,簡單耦合也使對象關系更加清晰,而且外部的調用方並不需要關系責任鏈是如何處理的。
責任鏈模式結構
- 處理者
聲明了所有具體處理者的通用接口,該接口通常僅包含單個方法用於請求處理,但有時其還會包含一個設置鏈上下處理者的方法。 - 基礎處理者
是一個可選的類,你可以將所有處理者共用的樣本代碼放置在其中。(通常情況下,該類定義了一個保存對於下個處理者引用的成員變量。客戶端可通過將處理者的構造函數或設定方法來創建鏈。該類還可以實現默認的處理行為,確定下個處理者存在后再將請求傳遞給它。) - 具體處理者
包含處理請求的實際代碼。每個處理者接收到請求后,都必須決定是否進行處理,或者說是否沿着鏈傳遞請求。 - 客戶端
可根據程序邏輯一次性或者動態的生成鏈。
適用場景
- 當程序需要使用不同方式處理不同種類請求,而且請求類型和順序預先未知時。
- 業務邏輯必須按順序執行多個處理者時。
- 處理者及其順序必須在運行時進行改變,可以使用責任鏈模式。
實現方式
- 聲明處理者接口並描述請求處理方法的簽名
- 可以根據處理者接口創建抽象處理者基類(需要一個成員變量來存儲指向鏈上下個處理者的引用)
- 創建具體的處理者子類並實現其處理方法。(每個處理者在接收到請求后都必須做兩個決定:1、是否自行處理請求;2、是否將該請求沿着鏈進行傳遞。)
- 客戶端可自行組裝鏈,或者從其他對象處獲得預先組裝好的鏈。
- 客戶端可觸發鏈中的任意處理者,而不僅僅是第一個。請求將通過鏈進行傳遞,直至某個處理者拒絕繼續傳遞或者請求到達鏈尾。
Demo
責任鏈模式在C#程序中並不常見,因為它僅在代碼與對象鏈打交道時才能發貨作用。
處理者接口
/// <summary>
/// 處理者接口
/// </summary>
public interface IHandler
{
IHandler SetNext(IHandler handler);
object Handle(object request);
}
抽象類
/// <summary>
/// 抽象類
/// </summary>
public abstract class AbstractHandler :IHandler
{
private IHandler _nextHandler;
public IHandler SetNext(IHandler handler)
{
this._nextHandler = handler;
return handler;
}
/// <summary>
/// 虛方法,在子類繼承中需實現此方法。
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public virtual object Handle(object request)
{
if (this._nextHandler !=null)
{
return this._nextHandler.Handle(request);
}
else
{
return null;
}
}
}
實現抽象類
/// <summary>
/// 猴子類
/// </summary>
public class MonkeyHandler : AbstractHandler
{
public override object Handle(object request)
{
if ((request as string)=="猴子")
{
return "在猴子類中"+request.ToString();
}
else
{
return base.Handle(request); //父類中的Handle方法
}
}
}
/// <summary>
/// 松鼠類
/// </summary>
public class SquirreHandler : AbstractHandler
{
public override object Handle(object request)
{
if ((request as string) == "松鼠")
{
return "在松鼠類中" + request.ToString();
}
else
{
return base.Handle(request); //父類中的Handle方法
}
}
}
/// <summary>
/// 小狗類
/// </summary>
public class DogHandler : AbstractHandler
{
public override object Handle(object request)
{
if ((request as string) == "小狗")
{
return "在小狗類中" + request.ToString();
}
else
{
return base.Handle(request); //父類中的Handle方法
}
}
}
客戶端和Main()驗證
class Client
{
public static void ClientCode(AbstractHandler handler)
{
foreach (var item in new List<string>{"松鼠","猴子","人"})
{
Console.WriteLine("到底是誰:"+item);
var result = handler.Handle(item);
if (result!=null)
{
Console.WriteLine("誰:"+result);
}
else
{
Console.WriteLine("No Find");
}
}
Console.WriteLine("開始");
}
}
class Program
{
static void Main(string[] args)
{
var monkey = new MonkeyHandler();
var squirrel = new SquirreHandler();
var dog = new DogHandler();
monkey.SetNext(squirrel).SetNext(dog); //構建鏈條
Console.WriteLine("----------第一次");
Client.ClientCode(monkey);
Console.WriteLine();
Console.WriteLine("第二次");
Client.ClientCode(squirrel);
Console.WriteLine("第三次");
Client.ClientCode(dog);
Console.ReadKey();
}
}

可以通過上面圖片標紅的地方了解到具體輸出的值,第一次(初始位置)時在最后狗類處不繼續執行,第二次(中間位置)在猴子類處不執行,第三次所有的都不執行(第三次到鏈尾了)。
小寄語
人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的。
我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩點贊、轉發 謝謝。
