(轉載請註明出處)
雖然委託結構靈活,而且其方法簽名可以適配的參數數量和類型更為豐富,但為了和其他第三方軟體、系統整合方面,工程中我們也許用到事件(Event)的機會更多。事件是委託的特例,“特”在如下4方面:
- 傳回值為void
- 第一個參數sender是System.Object
- 第二個參數繼承自EventArgs或其子類
- 僅限倆參數
就像事物的兩面一樣,事件約束較多對我們自己是這樣對其他開發人員也是這樣,所以在項目整合過程中,定義過於複雜的委託反而可能成為雙方的斷層,還需額外的適配器或觀察者解決問題,相對而言基於事件進行非同步通知整合更容易實現。下面我們看一個類比的監控程式:
需求是這樣的,我們需要對訂單的新增和修改進行記錄,新增相對好說,他的入口API固定,但訂單的欄位比較多,涉及的商務程序也複雜,修改API比較分散。我們的監控程式只需要知道新增多少條,總共進行過多少次修改,這時應用程式層通過事件監控不失為一個方法。
C#
業務實體和事件監控器
using System;
namespace MarvellousWorks.PracticalPattern.Concept.Delegating
{
/// business entity public class Order
{
public void Create() { EventMonitor.Added(this, null); }
public void ChangeDate() { EventMonitor.Modified(this, null); }
public void ChangeOwner() { EventMonitor.Modified(this, null); }
public void ChangeID() { } // do nothing } /// event monitor public static class EventMonitor
{
public static EventHandler<EventArgs> Modified;
public static EventHandler<EventArgs> Added;
static EventMonitor()
{
Modified = OnModified;
Added = OnAdded;
}
public static int ModifiedTimes
{
get;
private set;
}
public static int AddedTimes
{
get;
private set;
}
static void OnModified(object sender, EventArgs args) { ModifiedTimes++; }
static void OnAdded(object sender, EventArgs args) { AddedTimes++; }
}
}
C# Unit Test
[TestMethod]
public void EventMonitorSimulate()
{
Order order1 = new Order();
order1.Create(); // add 1 order1.ChangeDate(); // modify 1 order1.ChangeDate(); // modify 2 order1.ChangeOwner(); // modify 3 Order order2 = new Order();
order2.Create(); // add 2 order2.ChangeOwner(); // modify 4 order2.ChangeID(); // modify still 4 Assert.AreEqual<int>(2, EventMonitor.AddedTimes);
Assert.AreEqual<int>(4, EventMonitor.ModifiedTimes);
}
單元測試結果表明採用事件監控的可行性:
- 分散的業務實體物件其監控資訊可以集中反映在同一個監控器中
- 監控器可憑藉事件委託方式更新計數