委託(delegate
)是一種特殊的型別(class
),它可以被認為是一個可以擁有函數參照的類,它的宣告規定了它能夠持有的函數參照的函數形式,同時它可以儲存多個函數參照,並通過自己的方法呼叫所有註冊在它身上的方法(釋出者)。
理解了觀察者模式就理解了委託
它的特點在於:
delegate
來定義,而不是 class
event
關鍵字來修飾委託型別的變數,event
關鍵字包裝了委託型別的變數(事件變數不是委託變數,它們是兩個東西,儘管它們在宣告方式上很像,事件變數包裝了一個委託變數),這將避免從類外控制這個事件的釋出(Invoke
)namespace InterfaceTest
{
[TestClass]
public class DelegateTest
{
// 一個自定義的委託型別的變數,類比自定義的類的變數
public event Function calc;
[TestMethod]
public void TestMethod1()
{
calc += () =>
{
return 0.0;
};
calc += DelegateTest.C;
calc += new Function(C);
calc = calc + C;
calc.Invoke();
}
public static double C() { return 1.0; }
}
// 委託是一個型別,所以它可以直接定義在名稱空間下
// 無法為委託型別自定義方法
public delegate double Function();
public class Caller
{
public Caller()
{
var dt = new DelegateTest();
// 由於calc是一個event修飾的屬性,所以從外部呼叫Invoke將引發異常
dt.calc.Invoke(); // ERROR
}
}
}
string
型別一樣,我們也可以直接使用語言本身提供的 Action
和 Func
委託型別,它們已經包含了絕大多數可能的函數簽名的形式,而無需自定義自己的 「MyString」
在觀察者模式中主要有四個事物:釋出者、訂閱者、「訂閱」過程、「釋出」過程。
釋出者主要包含一個儲存了訂閱者參照的集合,在「釋出過程」發生時,通過這個訂閱者所持有的參照呼叫實現了相同介面的訂閱者的方法(在這一步有多種方式,不一定非要是介面,目的在於使釋出者能夠通過多型統一儲存所有的訂閱者,從而在「釋出」時遍歷整個集合呼叫所有訂閱者的方法。關於其它的實現方式可見參照.6)。
在委託中,觀察者模式的這四個部分的實現如下:
釋出者:委託型別的變數
訂閱者:符合委託型別定義的函數簽名的函數,表現形式有lambda表示式、直接定義的函數等(將函數當作一個函數型別的範例)
「訂閱」:+
-
,常見的形式是 +=
-=
,本質上是委託型別過載了 +
和 -
運運算元
「釋出」:
由系統負責「釋出」,程式設計師提供釋出時的動作(委託型別的函數):例如,WPF或Winform後置程式碼中的事件響應函數
由程式設計師負責「釋出」,系統負責提供釋出時的動作:例如,WPF中的OnPropertyChanged
在ViewModel中手動呼叫,但它上的函數的註冊在XAML解析時完成