本人部落格中的代碼都是本地測試通過,意思和注釋了解了就行
本篇文章引用張子陽部落格基本思路,然後根據自己的經驗,進行了部分的簡化和修改,委托就在于了解,多看幾遍就了解了。
委托:本質上講委托是一種可以将方法作為參數的方法,可以包含參數也可以不包含參數
事件:從本質上将也是委托,隻不過是進行了封裝的委托。事件可以綁定方法,綁定之後就會監視這些方法,當達到事件的觸發條件,就會執行事件綁定的方法
如果比較繞口的話請讀10遍就了解了
分五個步驟:
1.委托将方法作為參數傳遞:将方法作為參數進行傳遞,當某一個方法作為參數傳遞時,一起傳遞的還有這個方法對應的參數
舉例:
class Program
{
//定義委托
public delegate void GreetDelegate();
private static void EnglishGreeting(string name)
{
Console.WriteLine("Morning,"+name);
}
private static void ChaineseGreeting(string name)
{
Console.WriteLine("早上好,"+name);
}
//定義一個接收GreetingDelegate類型的方法
private static void GreetPeople(string name,GreetDelegate MakeGreeting)
{
MakeGreeting(name);
}
static void Main(string[] args)
{
//将方法作為參數傳遞,并同時傳遞方法執行需要的參數
GreetPeople("cdc",EnglishGreeting);
GreetPeople("奇點碼農",ChineseGreeting);
Console.ReadKey();
}
}
2.委托可以通過+=綁定方法,也可以通過-=消除委托對方法的綁定
//将方法綁定到委托
class Program
{
public delegate void GreetDelegateHandler(string name);
public static void EnglishGreeting(string name)
{
Console.WriteLine("Morning,"+name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("早上好,"+name);
}
static void Main(string[] args)
{
GreetDelegateHandler delegate1;
//将方法綁定到委托
delegate1=EnglishGreeting;
delegate1+=ChineseGreeting;
delegate1("cdc");
}
}
3.事件出馬:事件類似于進行了封裝的委托類型的變量,事件的參數與與之對應的委托的參數一緻
class Program
{
public delegate void GreetDelegateHandler(string name);
private static void EnglishGreeting(string name)
{
Console.WriteLine("Morning,"+name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("早上好,"+name);
}
public class GreetManager
{
public event GreetDelegateHandler GreetDelegate;
public void GreetPeople(string name)
{
//事件的參數與與之對應的委托的參數一緻
GreetDelegate(name);
}
}
static void Main(string[] args)
{
GreetManager gm=new GreetManager();
gm.GreetDelegate+=EnglishGreeting;
gm.GreetDelegate+=ChineseGreeting;
gm.GreetPeople("cdc");
Console.ReadKey();
}
}
4.Observer設計模式
(1)Subject:被監視對象,包含着其他對象感興趣的内容
(2)Observer:監視者,監視Subject,當Subject中的某事件發生的時候,會告知Observer,而Observer則會采取相應行動
//注:Observer設計模式是為了定義對象的一種一對多的依賴關系,以便當一個對象的狀态改變時,其他依賴于它的對象會自動告知并更新執行
//被監視對象
public class Heater
{
private int temperature;
//聲明委托
public delegate void BoilHandler(int param);
//使用委托聲明事件
public event BoilHandler BoilEvent;
//燒水
public void BoilWater()
{
for(int i=0;i<=100;i++)
{
Thread.Sleep(500);
temperature=i;
if(temperature>95)
{
if(BoilEvent!=null)
{
BoilEvent(temperature);
}
}
}
}
}
//監視者:警報器
public class Alarm
{
public void MakeAlert(int param)
{
Console.WriteLine("Alarm:滴滴。。。,水已經{0}度了",param);
}
}
//監視者:顯示器
public class Display
{
public static void ShowMsg(int param)
{
Console.WriteLine("Display:水快燒開了,目前溫度:{0}度",param);
}
}
class Program
{
static void Main(string[] args)
{
Heater heater=new Heater();
Alarm alarm=new Alarm();
//注冊方法
heater.BoilEvent+=alarm.MakeAlert;
//給匿名對象注冊方法
heater.BoilEvent+=(new Alarm()).MakeAlert;
//注冊靜态方法
heater.BoilEvent+=Display.ShowMsg;
//調用被監視對象執行方法,每當被監視對象的方法中觸發一次事件,就會将該事件綁定的所有監視者方法執行一遍
heater.BoilWater();
Console.ReadKey();
}
}
5.委托類型的代碼規範
(1)委托類型的名稱都應該以Event Handler結束
(2)委托的原型定義有一個void傳回值,并接收兩個輸入參數:一個Object類型,一個EventArgs類型(或者繼承自EventArgs)
(3)事件的命名為委托去掉EventHandler之後的剩餘部分
(4)繼承自EventArgs的類型應該以EventArgs結尾
//熱水器
public class Heater
{
private int temperature;
//添加型号作為示範
public string type="RealFire001";
//添加産地作為示範
public string area="China Xian";
//聲明委托
public delegate void BoiledEventHandler(object sender,BoiledEventArgs e);
//聲明事件
public event BoiledEventHandler Boiled;
//定義BoiledEventArgs類,傳遞給Observer所感興趣的資訊
public class BoiledEventArgs:EventArgs
{
public readonly int temperature;
public BoiledEventArgs(int temperature)
{
this.temperature=temperature;
}
}
//可以供繼承自Heater類的重寫,以便繼承類拒絕其他對象對它的監視
protected virtual void OnBoiled(BoiledEventArgs e)
{
//如果該事件已經注冊方法,則觸發對應的方法
if(Boiled!=null)
{
//調用所有注冊對象的方法
Boiled(this,e);
}
}
//燒水
public void BoilWater()
{
for(int i=90;i<=100;i++)
{
Thread.Sleep(500);
temperature=i;
if(temperature>95)
{
//建立Boiled的EventArgs對象
BoiledEventArgs e=new BoiledEventArgs(temperature);
OnBoiled(e);
}
}
}
}
//螢幕:警報器
public class Alarm
{
public void MakeAlert(object sender,Heater.BoiledEventArgs e)
{
Heater heater=(Heater)sender;
//通路sender中的公共字段
Console.WriteLine("Alarm:{0}-{1}:",heater.area,heater.type);
Console.WriteLine("Alarm:滴滴,水溫{0}度!",e.temperature);
Console.WriteLine();
}
}
//螢幕:顯示器
public class Display
{
public static void ShowMsg(object sender,Heater.BoiledEventArgs e)
{
Heater heater=(Heater)sender;
Console.WriteLine("Display:{0}-{1}:",heater.area,heater.type);
Console.WriteLine("Display:顯示水溫{0}度。",e.temperature);
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
Heater heater=new Heater();
Alarm alarm=new Alarm();
//注冊方法
heater.Boiled+=alarm.MakeAlert;
//給匿名對象注冊方法
heater.Boiled+=(new Alarm()).MakeAlert;
//注冊方法
heater.Boiled+=new Heater.BoiledEventHandler(alarm.MakeAlert);
//注冊靜态方法
heater.Boiled+=Display.ShowMsg;
//調用燒水的方法,會自動調用注冊的方法
heater.BoilWater();
Console.ReadKey();
}
}