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

C# 事件/委派 vs 觀察者模式:核心對比與代碼對照

     編輯:關於C#

C# 事件(event)本質上是觀察者模式的語言級內建實作。本文透過並列代碼對照,展示 delegate/event 如何對應觀察者模式的 Subject、Observer、Attach/Detach、Notify、Update 角色,幫助開發者從設計模式角度理解事件機制。

核心對照表

觀察者模式角色C# 事件對應說明
Subject(被觀察者)擁有 event 的類別(如 ListWithChangedEvent)維護觀察者清單,狀態改變時觸發通知
Observer(觀察者)訂閱事件的類別(如 EventListener)實作處理方法(Update),註冊到 Subject
Attachevent += handler將委派加入調用清單
Detachevent -= handler從調用清單移除委派
NotifyOnChanged() 呼叫 event(this, e)遍歷調用清單依序執行每個委派
Update事件處理方法(ListChanged)觀察者回應通知的邏輯
事件參數EventArgs / 自訂 XxxEventArgs攜帶狀態變更資訊

並列代碼範例

觀察者模式手動實作(簡化)


interface IObserver { void Update(object sender, EventArgs e); }
interface ISubject { void Attach(IObserver o); void Detach(IObserver o); void Notify(); }

class Subject : ISubject
{
    private List _obs = new List();
    public void Attach(IObserver o) => _obs.Add(o);
    public void Detach(IObserver o) => _obs.Remove(o);
    public void Notify() => _obs.ForEach(o => o.Update(this, EventArgs.Empty));
}

C# 事件實作(同功能)


public delegate void ChangedEventHandler(object sender, EventArgs e);

class ListWithChangedEvent : ArrayList
{
    public event ChangedEventHandler Changed; // 事件 = 內建觀察者清單

    protected virtual void OnChanged(EventArgs e)
    {
        Changed?.Invoke(this, e); // Null-conditional 呼叫 = Notify
    }

    public override int Add(object value)
    {
        int i = base.Add(value);
        OnChanged(EventArgs.Empty); // 狀態改變觸發通知
        return i;
    }
    // Clear、Indexer setter 同理呼叫 OnChanged
}

class EventListener
{
    private ListWithChangedEvent _list;
    public EventListener(ListWithChangedEvent list)
    {
        _list = list;
        _list.Changed += ListChanged; // Attach
    }
    private void ListChanged(object sender, EventArgs e) // Update
    {
        Console.WriteLine("列表已變更");
    }
    public void Detach() => _list.Changed -= ListChanged; // Detach
}

事件優於手動觀察者的優勢

  • 語法糖:event 關鍵字限制外部只能 +=/-=,不能直接 = 覆蓋或 () 呼叫,封裝性更好。
  • 多播委派:自動維護調用清單,執行緒安全(委派不可變、新增/移除產生新實例)。
  • 標準化:EventHandler<TEventArgs>、EventArgs、sender 慣例,工具支援完善。
  • 編譯器/IDE 支援:智慧感知、自動產生處理方法、導航至訂閱點。

進階主題

  • 弱事件模式:避免觀察者被 Subject 強參考導致記憶體洩漏(WeakEventManager、WeakReference)。
  • 事件存取器:event X { add { } remove { } } 自訂儲存邏輯(如壓縮儲存、轉發)。
  • 非同步事件:await event.InvokeAsync(...)(需自行實作或用 AsyncEventHandler 模式)。
  • 領域事件:DDD 中實體發佈領域事件,由薄層處理器訂閱,解耦領域邏輯與基礎設施。

理解事件與觀察者模式的對應關係,不僅能寫出更地道的 C# 代碼,也能在架構設計中靈活選擇「語言內建事件」或「手動觀察者/中介者/訊息總線」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved