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

C# 委派與事件實作觀察者模式

     編輯:關於C語言

前言

在 C# 中,委派與事件是實作「觀察者模式」的核心機制。委派封裝方法,事件則標準化委派的發布/訂閱模型,讓物件之間保持鬆散耦合。本文將從委派基礎、事件語法、到完整觀察者模式範例,逐步深入解析。

一、委派基礎

1.1 委派宣告

委派定義一種型別,封裝具有特定參數與回傳值的方法:

public delegate void PrintHandler(string str);

此宣告定義了 PrintHandler 型別,可指向任何回傳 void、接受單一 string 參數的方法。

1.2 委派實例化與呼叫

PrintHandler handler = new PrintHandler(MyPrintMethod);
// 或簡寫
PrintHandler handler = MyPrintMethod;

if (handler != null)
    handler("Hello World");

1.3 多播委派

委派可串聯多個方法,使用 +=、-= 或 Delegate.Combine/Remove:

handler += AnotherMethod;
handler -= MyPrintMethod;

呼叫時會依序執行鏈結串列中的所有方法。

二、事件機制

2.1 事件宣告規範

事件本質是特殊的多播委派,.NET 規範要求事件委派簽名必須符合:

  1. 兩個參數:object sender(事件來源)、EventArgs e(事件資料)
  2. e 型別必須為 EventArgs 或其衍生類別
public delegate void CustomEventHandler(object sender, EventArgs e);
public event CustomEventHandler OnCustomEvent;

2.2 引發事件

僅能在宣告事件的類別內部引發,習慣先檢查 null:

protected virtual void RaiseEvent(EventArgs e)
{
    if (OnCustomEvent != null)
        OnCustomEvent(this, e);
}

2.3 訂閱與取消訂閱

外部物件透過 +=/-= 註冊處理方法:

publisher.OnCustomEvent += HandlerMethod;
publisher.OnCustomEvent -= HandlerMethod;

三、觀察者模式實戰:員工玩遊戲扣薪水

3.1 緊密耦合的缺點

若 Employee 直接參考 Manager 並呼叫其方法,會導致:

  • 建立 Employee 必須先有 Manager 實例
  • 需求變更(如改由保安處罰、新增扣績效)時,必須修改 Employee 類別

3.2 使用事件解耦

步驟 1:定義事件委派與事件引數

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

public class PlayGameEventArgs : EventArgs
{
    public string EmployeeName { get; set; }
}

步驟 2:發布者 - Employee 類別

public class Employee
{
    public event PlayGameHandler PlayGame;
    public string Name { get; set; }
    public int Salary { get; set; } = 1000;

    public void Play()
    {
        Console.WriteLine($"{Name} 開始玩遊戲...");
        OnPlayGame(new PlayGameEventArgs { EmployeeName = Name });
    }

    protected virtual void OnPlayGame(PlayGameEventArgs e)
    {
        PlayGame?.Invoke(this, e);
    }
}

步驟 3:訂閱者 - Manager 類別

public class Manager
{
    public void DeductSalary(object sender, PlayGameEventArgs e)
    {
        var emp = sender as Employee;
        if (emp != null)
        {
            Console.WriteLine($"主管發現 {emp.Name} 玩遊戲,扣薪 500 元");
            emp.Salary -= 500;
        }
    }
}

步驟 4:客戶端程式碼組裝

var emp = new Employee { Name = "小張" };
var mgr = new Manager();

// 訂閱事件
emp.PlayGame += mgr.DeductSalary;

Console.WriteLine($"原薪資:{emp.Salary}");
emp.Play();
Console.WriteLine($"現薪資:{emp.Salary}");

3.3 需求變更時的優勢

  • 換人處理:只需在客戶端將訂閱對象換為 SecurityGuard 實例,Employee 完全不需修改。
  • 多重處理:可同時訂閱 mgr.DeductSalary 與 hr.DeductPerformance,單一事件觸發多個回應。

四、WinForm/WebForm 中的事件應用

按鈕點擊事件即是典型觀察者模式:

this.button1.Click += new EventHandler(this.Button1_Click);

private void Button1_Click(object sender, EventArgs e)
{
    // 處理邏輯
}

五、總結

委派與事件讓 C# 能以極少代碼實作觀察者模式,核心三要素:

  1. 事件來源(如 Employee)
  2. 事件處理者(如 Manager)
  3. 委派型別 連結兩者

善用此機制,可大幅降低類別間耦合,提升系統擴充性與維護性。

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