class Worker {
public void Advise(Boss boss) { _boss = boss; }
public void DoWork() {
Console.WriteLine("工作開始");
if (_boss != null) _boss.WorkStarted();
Console.WriteLine("工作中...");
if (_boss != null) _boss.WorkProgressing();
Console.WriteLine("工作完成");
if (_boss != null) {
int grade = _boss.WorkCompleted();
Console.WriteLine($"得分:{grade}");
}
}
private Boss _boss;
}
class Boss {
public void WorkStarted() { }
public void WorkProgressing() { }
public int WorkCompleted() { return 2; }
}
缺點:Worker 強依賴 Boss 具體類,無法擴展新監聽者 (如 Universe)。
interface IWorkerEvents {
void WorkStarted();
void WorkProgressing();
int WorkCompleted();
}
class Worker {
public void Advise(IWorkerEvents events) { _events = events; }
// ... 調用 _events.xxx()
private IWorkerEvents _events;
}
class Boss : IWorkerEvents { ... }
class Universe : IWorkerEvents { ... }
缺點:接口粒度粗,Boss 被迫實現不關心的方法 (空實現),違反接口隔離原則。
delegate void WorkStarted();
delegate void WorkProgressing();
delegate int WorkCompleted();
class Worker {
public WorkStarted started;
public WorkProgressing progressing;
public WorkCompleted completed;
public void DoWork() {
Console.WriteLine("工作開始"); if (started != null) started();
Console.WriteLine("工作中..."); if (progressing != null) progressing();
Console.WriteLine("工作完成"); if (completed != null) { int g = completed(); Console.WriteLine($"得分:{g}"); }
}
}
class Boss { public int WorkCompleted() { return 4; } }
class Universe {
static void WorkerStartedWork() { Console.WriteLine("Universe 注意到..."); }
static int WorkerCompletedWork() { return 7; }
static void Main() {
var p = new Worker();
p.completed = new WorkCompleted(new Boss().WorkCompleted);
p.started = new WorkStarted(Universe.WorkerStartedWork);
p.completed = new WorkCompleted(Universe.WorkerCompletedWork); // 覆蓋 Boss!
p.DoWork();
}
}
缺點:public 委托字段可被任意覆蓋/直接調用 (破壞封裝),無法多播。
class Worker {
public event WorkStarted started;
public event WorkProgressing progressing;
public event WorkCompleted completed;
// DoWork 內部調用不變
}
// 使用 += / -= 訂閱/退訂,不可直接賦值或調用
p.completed += new WorkCompleted(boss.WorkCompleted);
p.started += new WorkStarted(Universe.WorkerStartedWork);
event 關鍵字編譯器生成 `add_XXX`/`remove_XXX` 存取器,僅暴露 `+=`/`-=`。
if (completed != null) {
foreach (WorkCompleted wc in completed.GetInvocationList()) {
int grade = wc();
Console.WriteLine($"得分:{grade}");
}
}
foreach (var wc in completed.GetInvocationList())
wc.BeginInvoke(null, null); // 線程池執行,主線程立即返回
foreach (var wc in completed.GetInvocationList()) {
var ar = wc.BeginInvoke(null, null);
while (!ar.IsCompleted) Thread.Sleep(1);
int grade = wc.EndInvoke(ar);
Console.WriteLine($"得分:{grade}");
}
foreach (var wc in completed.GetInvocationList())
wc.BeginInvoke(new AsyncCallback(WorkGraded), wc);
private void WorkGraded(IAsyncResult ar) {
var wc = (WorkCompleted)ar.AsyncState;
int grade = wc.EndInvoke(ar);
Console.WriteLine($"得分:{grade}");
}
主線程完全解放,完成時自動回調處理結果。
「他們永遠幸福地生活下去……直到下一個重構需求到來。」