本人博客中的代码都是本地测试通过,意思和注释理解了就行
本篇文章引用张子阳博客基本思路,然后根据自己的经验,进行了部分的简化和修改,委托就在于理解,多看几遍就理解了。
委托:本质上讲委托是一种可以将方法作为参数的方法,可以包含参数也可以不包含参数
事件:从本质上将也是委托,只不过是进行了封装的委托。事件可以绑定方法,绑定之后就会监视这些方法,当达到事件的触发条件,就会执行事件绑定的方法
如果比较绕口的话请读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();
}
}