C#中的EventHandler觀察者模式詳解
C# 和 java 比較:java 中使用的是接口。C# 使用委托機(jī)制,可以用時(shí) + 運(yùn)算符進(jìn)行注冊,直接多播。而 java 中是一般是使用一個(gè)集合來保存觀察者。
一、解釋
發(fā)布者(Publisher)= 被觀察者(Observable) = 事件源(java中的EventObject,C#中的sender)
訂閱者(Subscriber)=觀察者(Observer)= 接收者(java中繼承EventLister,接口, 或Observer接口, C#由于委托機(jī)制,不需要繼承接口,直接按EventHandler實(shí)現(xiàn)回調(diào)方法)
在發(fā)生其他類或?qū)ο箨P(guān)注的事情時(shí),類或?qū)ο罂赏ㄟ^事件通知它們。發(fā)送(或引發(fā))事件的類稱為“發(fā)行者”,接收(或處理)事件的類稱為“訂戶”。在典型的 C# Windows 窗體或 Web 應(yīng)用程序中,可訂閱由控件(如按鈕和列表框)引發(fā)的事件。可使用 Visual C# 集成開發(fā)環(huán)境 (IDE) 來瀏覽控件發(fā)布的事件,選擇要處理的事件。IDE 會(huì)自動(dòng)添加空事件處理程序方法和訂閱事件的代碼。
EventHandler 為 C# 中的預(yù)定義委托,專用于表示不生成數(shù)據(jù)的事件的事件的處理程序方法。
public delegate void EventHandler(Object sender, EventArgs e)
二、事件具有以下特點(diǎn):
1. 發(fā)行者確定何時(shí)引發(fā)事件,訂戶確定執(zhí)行何種操作來響應(yīng)該事件。
2. 一個(gè)事件可以有多個(gè)訂戶。一個(gè)訂戶可處理來自多個(gè)發(fā)行者的多個(gè)事件。
3. 沒有訂戶的事件永遠(yuǎn)不會(huì)被調(diào)用。
4. 事件通常用于通知用戶操作(如:圖形用戶界面中的按鈕單擊或菜單選擇操作)。
5. 如果一個(gè)事件有多個(gè)訂戶,當(dāng)引發(fā)該事件時(shí),會(huì)同步調(diào)用多個(gè)事件處理程序。要異步調(diào)用事件,請參見使用異步方式調(diào)用同步方法。
6. 可以利用事件同步線程。
7. 在 .NET Framework 類庫中,事件是基于 EventHandler 委托和 EventArgs 基類的。
實(shí)例代碼
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleAppEventArgs { public class Program { public static void Main(string[] args) { Publisher pub = new Publisher(); Subscriber sub1 = new Subscriber("sub1",pub); Subscriber sub2 = new Subscriber("sub2", pub); // 調(diào)用這個(gè)方法來產(chǎn)生事件 pub.DoSomething(); Console.WriteLine("Press Enter to close this window."); Console.ReadLine(); } } /// <summary> /// 自定義一個(gè)事件類來保存事件信息 /// </summary> public class CustomEventArgs : EventArgs public CustomEventArgs(string s) private string message; public string Message get { return message; } set { message = value; } /// 廣播事兒件的類 public class Publisher //使用EventHandler<T> 聲明一個(gè)事件 public event EventHandler<CustomEventArgs> RaiseCustomEvent; public void DoSomething() //DoSomething………… // 你也可以再觸發(fā)事件前,執(zhí)行一些其他的代碼 OnRaiseCustomEvent(new CustomEventArgs("Did something,hi 這是事件消息")); protected virtual void OnRaiseCustomEvent(CustomEventArgs e) // 定義一個(gè)局部變量,已防止最后一個(gè)訂閱者剛好在檢查null后取消訂閱 EventHandler<CustomEventArgs> handler = RaiseCustomEvent; // 如果沒有 訂閱者(觀察者), 委托對象將為null if (handler != null) { // 格式化事件消息中 的字符串 e.Message += String.Format(" at {0}", DateTime.Now.ToString()); // 這是最重要的一句。 // 此時(shí)執(zhí)行的 handler已經(jīng)是一個(gè)多播委托(如果有多個(gè)訂閱者或觀察者注冊)。 // 既然是多播委托,就可以依次調(diào)用各個(gè) 回調(diào)函數(shù) (既然是回調(diào)函數(shù),實(shí)際的執(zhí)行就由訂閱者類決定)。 //這里面?zhèn)魅胍粋€(gè)this, 就代表 事件源(或發(fā)布者 或 被觀察者 都一個(gè)意思) handler(this, e); } /// 用來注冊事件的類 public class Subscriber private string id; public Subscriber(string ID, Publisher pub) id = ID;//注冊這個(gè)動(dòng)作,應(yīng)該有訂閱者主動(dòng)進(jìn)行,并且可以再后期取消注冊 pub.RaiseCustomEvent += HandleCustomEvent; // 實(shí)現(xiàn)回調(diào)函數(shù)。在事件發(fā)生后,執(zhí)行什么樣的操作。這里只是簡單的打印信息。 void HandleCustomEvent(object sender, CustomEventArgs e) //這就是實(shí)際的操作。 Console.WriteLine(id + " received this message: {0}", e.Message); }
到此這篇關(guān)于C# EventHandler觀察者模式的文章就介紹到這了,更多相關(guān)C# 觀察者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何使用LinQ To Object把數(shù)組或DataTable中的數(shù)據(jù)進(jìn)行向上匯總
這篇文章主要介紹了如何使用LinQ To Object把數(shù)組或DataTable中的數(shù)據(jù)進(jìn)行向上匯總,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12c#定時(shí)器和global實(shí)現(xiàn)自動(dòng)job示例
這篇文章主要介紹了c#定時(shí)器和global實(shí)現(xiàn)自動(dòng)job示例,大家參考使用吧2014-01-01C#學(xué)習(xí)筆記- 隨機(jī)函數(shù)Random()的用法詳解
下面小編就為大家?guī)硪黄狢#學(xué)習(xí)筆記- 隨機(jī)函數(shù)Random()的用法詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08C#中自定義高精度Timer定時(shí)器的實(shí)例教程
這篇文章主要介紹了C#中自定義高精度Timer定時(shí)器的實(shí)例教程,多線程的Timer編寫需要注意線程安全的問題,需要的朋友可以參考下2016-04-04AjaxControlToolkit AjaxFileUpload 顯示英文改成中文的解決方法
AjaxControlToolkit AjaxFileUpload 顯示英文改成中文的解決方法,需要的朋友可以參考一下2013-03-03