責任鏈模式介紹
責任鏈模式是一種行為設計模式,允許你將請求沿著處理者鏈進行發送,收到請求后,每個處理者均可對請求進行處理,或將其傳遞給鏈上的下個處理者,
責任鏈模式的核心是解決一組服務中的先后執行處理關系,
責任鏈模式可以讓各個服務模塊更加清晰,而每一個模塊可以通過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();
}
}
可以通過上面圖片標紅的地方了解到具體輸出的值,第一次(初始位置)時在最后狗類處不繼續執行,第二次(中間位置)在猴子類處不執行,第三次所有的都不執行(第三次到鏈尾了),
小寄語
人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的,
我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩點贊、轉發 謝謝,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/295527.html
標籤:.NET技术
