首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 觀察者模式實作:委派與事件實現發佈-訂閱機制完整教學

     編輯:關於C語言

模式意圖

觀察者模式定義物件間的一對多依賴,當主題狀態改變時,自動通知所有觀察者。C# 內建 delegate 與 event 關鍵字,使此模式實作極為自然。

核心概念對應

觀察者術語C# 對應
Subject(主題)擁有 event 的類別(如 CCollection)
Observer(觀察者)訂閱事件的類別(如 BusinessObject)
通知引發 event
回呼委派方法

完整範例:集合變更通知


using System;

// 事件參數:攜帶 Key/Value
class ItemEventArgs : EventArgs
{
    public readonly string Key;
    public readonly long Value;
    public ItemEventArgs(string key, long value) { Key = key; Value = value; }
}

// 主題:集合類別
class ObservableCollection
{
    // 1. 定義委派型別
    public delegate void ItemAddedHandler(object sender, ItemEventArgs e);

    // 2. 宣告事件
    public event ItemAddedHandler ItemAdded;

    // 3. 觸發事件的受保護方法
    protected virtual void OnItemAdded(ItemEventArgs e)
    {
        ItemAdded?.Invoke(this, e); // C# 6.0+ null 條件運算子
    }

    // 業務方法
    public void AddItem(string key, long value)
    {
        // ... 實際新增邏輯 ...
        OnItemAdded(new ItemEventArgs(key, value));
    }
}

// 觀察者:業務物件
class BusinessObject
{
    private string _name;

    public BusinessObject(ObservableCollection coll, string name)
    {
        _name = name;
        // 訂閱事件(使用 += 運算子)
        coll.ItemAdded += OnItemAdded;
    }

    // 事件處理器
    private void OnItemAdded(object sender, ItemEventArgs e)
    {
        Console.WriteLine($"[{_name}] 收到新項目: Key={e.Key}, Value={e.Value}");
    }
}

// 測試
class Program
{
    static void Main()
    {
        var coll = new ObservableCollection();
        var bo1 = new BusinessObject(coll, "BO-1");
        var bo2 = new BusinessObject(coll, "BO-2");

        coll.AddItem("UserCount", 100);
        coll.AddItem("OrderID", 2024001);
    }
}

執行結果


[BO-1] 收到新項目: Key=UserCount, Value=100
[BO-2] 收到新項目: Key=UserCount, Value=100
[BO-1] 收到新項目: Key=OrderID, Value=2024001
[BO-2] 收到新項目: Key=OrderID, Value=2024001

進階主題

取消訂閱


coll.ItemAdded -= OnItemAdded; // 必須使用相同的委派實例

弱事件模式

長生命週期的主題持有短生命週期觀察者的強參考會造成記憶體洩漏。可使用 WeakEventManager (WPF) 或自訂弱參考包裝器解決。

非同步通知


// 非同步引發(需自行管理執行緒)
Task.Run(() => OnItemAdded(e));

最佳實務

  • 事件命名用動詞過去分詞:ItemAdded、OrderCompleted。
  • 委派簽名遵循 (object sender, TEventArgs e) 慣例。
  • 引發事件前用 ?.Invoke 防止 null 參考。
  • 實作 IDisposable 時在 Dispose 中取消訂閱。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved