------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
声明委托的方式:delegate 返回值类型 委托类型名(参数) 比如delegate void StringProcess(string s); 注意这里的除了前面的delegate,剩下部分和声明一个函数一样,但是StringProcess不是函数名,而是委托类型名
存储什么样的方法就声明什么类型(方法参数与返回值)的委托。
声明的委托是一种类型,就像int、Person一样,如果要用的话还要声明委托类型的变量,声明委托类型变量的方式:StringProcess f1;
将委托类型变量指向函数 StringProcess sp = new StringProcess(SayHello),这样就可以像调用普通函数一样把sp当成函数用了。
委托可以看做是函数的指针。整数可以用整数变量指向它,对象可以用对象变量指向它,函数也可以用委托变量指向它。
和直接调用函数的区别:用委托就可以指向任意的函数,哪怕是之前没定义的都可以,而不使用受限于那几种。
将委托类型变量指向函数还可以简化成StringProcess sp = SayHello,编译器帮我们进行了new。但是不能sp=PrintIt(),因为这样就成了函数调用。
委托类型的名称都应该以EventHandler结束。 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。 事件的命名为 委托去掉 EventHandler之后剩余的部分。 继承自EventArgs的类型应该以EventArgs结尾。
委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。 EventArgs 对象包含了Observer所感兴趣的数据,在本例中是temperature。上面这些其实不仅仅是为了编码规范而已,这样也使得程序有更大的灵活性。比如说,如果我们不光想获得热水器的温度,还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得很麻烦,而如果我们将热水器的引用传给警报器的方法,就可以在方法中直接访问热水器了。
下面例子是一个实现烧水,并发出警报的模拟过程。现在假设热水器由三部分组成:热水器、警报器、显示器,它们来自于不同厂商并进行了组装。那么,应该是热水器仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由警报器发出警报、显示器显示提示和水温。
警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。 热水器知道后保留对警报器和显示器的引用。 热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方 法。 类似这样的例子是很多的,GOF对它进行了抽象,称为Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 委托学习
{
class DotNetFormal_Heater
{
private int tempterture;//温度
public string type = "这是类型";//测试数据
public string area = "大中华区产";//测试数据
//声明委托
public delegate void BoildEventHandler(Object sender, BoiledEventArgs e);
public event BoildEventHandler Boiled;//声明事件
/// <summary>
/// 定义BoiledEventArgs类,传递Observer所感兴趣的信息
/// </summary>
public class BoiledEventArgs : EventArgs
{
public readonly int temperture;
public BoiledEventArgs(int term)
{
this.temperture = term;
}
}
/// <summary>
/// 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视
/// </summary>
/// <param name="e"></param>
protected virtual void OnBoild(BoiledEventArgs e)
{
if (Boiled != null)//如果有对象注册
{
Boiled(this, e);//调用所有注册对象的方法
}
}
/// <summary>
/// 烧水
/// </summary>
public void BoilWater()
{
for (int i = 0; i <=100; i++)
{
this.tempterture = i;
if (tempterture>95)
{
//建立建立BoiledEventArgs 对象。
BoiledEventArgs e = new BoiledEventArgs(this.tempterture);
OnBoild(e);//调用OnBolied方法
}
}
}
}
//警报器的类
class Alarm
{
public void MakeAlert(object sender,DotNetFormal_Heater.BoiledEventArgs e)
{
DotNetFormal_Heater heater = (DotNetFormal_Heater)sender;
//访问 sender 中的公共字段
Console.Write("Alarm:{0}--{1}", heater.area, heater.type);
Console.WriteLine("Alarm:嘟嘟嘟,水已经{0}度了",e.temperture);
}
}
class Display
{
public void ShowMsg(object sender, DotNetFormal_Heater.BoiledEventArgs e)
{
DotNetFormal_Heater heater = (DotNetFormal_Heater)sender;
//访问 sender 中的公共字段
Console.Write("Display:{0}--{1}", heater.area, heater.type);
Console.WriteLine("Display:嘟嘟嘟,水快烧开了,当前温度是{0}度.", e.temperture);
}
}
class program
{
static void Main()
{
DotNetFormal_Heater heater = new DotNetFormal_Heater();
Alarm alarm=new Alarm ();
heater.Boiled += alarm.MakeAlert;//警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。
heater.Boiled+=(new Display()).ShowMsg;//给匿名对象注册方法
// heater.Boiled += new DotNetFormal_Heater.BoildEventHandler(alarm.MakeAlert);
heater.BoilWater();
Console.ReadKey();
}
}
}
------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------