事件与委托
?? 網上有好多講委托與事件的文章,寫得都很不錯,以下是我對事件與委托的理解,若有不當之處,請提出,萬分感謝。
?? 為了方便閱讀,我將代碼寫在了后面,前面介紹了一些跟代碼有關的信息。
? Observe模式中,主體subject指受監控者,觀察者observer指監控者。內存狀態(MemeryStatus)是受監控者,屬于主體;Observer是監控者,屬于觀察者;
? 主體中往往有一個或多個觀察者感興趣的信息,此例中式currentVolume,即當前內存容量,主體中還應該有定義好的事件,主體中的事件在客戶端(一般指含有Main函數的類)與觀察者中的處理方法綁定,當主體滿足某一條件時(此例中指滿足currentVolume>95時),就應該激發事件(此例中指MemeryObserve(this, args);),之后,與該事件綁定的所有觀察者端的處理方法都會執行(這叫回調),這樣,通過事件,將主體端的狀態變化和觀察者端的監控相關聯,主體變化,觀察者就能做出相應變化了。
???? ?換種方式看本例程序,其實很熟悉,打開VS新建一個C# Winform應用程序,在默認窗體中拖放一個button控件,雙擊該控件,在Form1.cs中將會自動生成單擊處理程序
??????? private void button1_Click(object sender, EventArgs e)
??????? {
??????? }
仔細一看,該處理方法跟本例Observer類中的? public void Warning(object sender, MemeryObserveEventArgs args)很相似最后一個參數稍微有些差別,這是因為各自定義的事件參數不同, 在void Warning(object sender, MemeryObserveEventArgs args)中,我們要獲得subject(主體)的當前容量,即currentVolume,而在void button1_Click(object sender, EventArgs e)中,我們可能?要獲取其他與subject有關的信息,打開Form1.Designer.cs文件,展開"Windows 窗體設計器生成的代碼"你會找到"this.button1.Click += new System.EventHandler(this.button1_Click)"這句代碼,再仔細一看,你會發現它跟本例寫過的?status.MemeryObserve+=new MemeryObserveEventHandler(observer.Warning);這句很相似。我們知道,MemeryObserveEventHandler是我們定義的一個委托,它的方法簽名要求這樣的形式"void 函數名(object param1,MemeryObserveEventArgs param2)",那么,System.EventeHandler其實也是個委托,類似這樣定義:public delegate void EventHandler(object sender,EventArgs args).所以,button類就是Observer模式中的主體,相當于本例 中的MemeryStatus類 ,this.button1相當于本例中的status(事件發布者),Form1(即窗體類)就相當于本例中的observer(觀察者)。這樣,觀察者(Form1)觀察被觀察者(Button)的狀態變化(比如被單擊),作出相應的動作(執行void Warning(object sender, MemeryObserveEventArgs args))。
我們現在來比較一下本例程序和新建winform默認程序
1、本例中主體(即事件發布者)為MemeryStatus類,winform中的主體為Button類;
2、本例中事件為MemeryObserve,winform中事件為Click;
3、本例中事件參數類為MemeryObserveEventArgs,winform中事件參數類為EventArgs;
4、本例中觀察者(即事件訂閱者)為Observer類,winform中觀察者為窗體,即Form1類;
5、本例中當事件發生,回調函數為?public void Warning(object sender, MemeryObserveEventArgs args)?,winform中回調函數為private void??? button1_Click(object sender, EventArgs e);
6、本例中當內存已用容量大于95時,觸發事件MemeryObserve,winform中當用戶點擊按鈕時,觸發事件Click;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
??? public class MemeryObserveEventArgs : EventArgs??? //事件參數類
??? {
??????? private readonly int currentVolume;
??????? public int CurrentVolume
??????? {
??????????? get
??????????? {
??????????????? return currentVolume;
??????????? }
??????? }
??????? public MemeryObserveEventArgs(int C)
??????? {
??????????? this.currentVolume = C;
??????? }
??? }
??? public delegate void MemeryObserveEventHandler(object sender,MemeryObserveEventArgs args);? //委托
??? public class MemeryStatus??????????????????????? //subject,主體/publisher,事件發布者
??? {
??????? private int currentVolume;
??????? public event MemeryObserveEventHandler MemeryObserve;?? //定義待激發事件
??????? public int CurrentVolume
??????? {
??????????? get
??????????? {
??????????????? return currentVolume;
??????????? }
??????????? set
??????????? {
??????????????? if (value > 95)????????????????????????? //給實例currentVolume賦值,如果當前已用容量大于95,則激發事件MemeryObserve
??????????????? {
??????????????????? currentVolume = value;
??????????????????? if (MemeryObserve != null)??????????? //如果事件有方法綁定
??????????????????? {
??????????????????????? MemeryObserveEventArgs args=new MemeryObserveEventArgs(value);? //構建事件參數
??????????????????????? MemeryObserve(this, args);?????????? //激發事件
??????????????????? }
??????????????? }
??????????? }
??????? }
??? }
??? public class Observer?????????????????????????????? //觀察者,observer/事件訂閱者
??? {
??????? public void Warning(object sender, MemeryObserveEventArgs args)? //observer方的處理方法,應和前面聲明的委托有同樣的方法簽名
??????? {
??????????? Console.Write("當前容量超過上限容量{0}\n", args.CurrentVolume);
??????? }
??? }
??? class Program??????????????????????????????????????? //客戶端
??? {
??????? static void Main(string[] args)
??????? {
??????????? MemeryStatus status = new MemeryStatus(); //創建subject實例
??????????? Observer observer = new Observer();?? //創建observer實例
??????????? status.MemeryObserve+=new MemeryObserveEventHandler(observer.Warning);? //將observer方的處理方法(observer.Warning)綁定到subject方(status.MemeryObserve)事件
??????????? for (int i = 1; i < 100; i++)
??????????? {
??????????????? status.CurrentVolume = i;?? //以此增加subject方的當前容量,當滿足一定條件時,會激發subject方的事件
??????????? }
??????????? Console.Read();
??????? }
??? }
}
//輸出結果:
//當前容量超過上限容量96
//當前容量超過上限容量97
//當前容量超過上限容量98
//當前容量超過上限容量99
//本代碼在VS2008中運行通過
轉載于:https://www.cnblogs.com/xiaozhi_5638/archive/2010/01/13/1646836.html
總結
- 上一篇: 逻辑有两种
- 下一篇: dailybuild