一: 基本概念
1、委托(Delegate)
概念:对某个方法引用的一种引用类型变量。注意看概念, 委托是一种引用类型变量, 类型变量,因此可以将委托当作方法的参数进行传递。 通俗点来讲,委托有点像方法的快捷方式, 通过委托可以执行方法。
声明: 在类中声明, 其声明决定了该委托可用的方法。也就是说,委托只可指向具有相同标签(参数、返回值)的方法。
举个例子:
1 // 声明委托
2 public delegate double MyDelegate(string s);
3 // 创建方法
4 public double GetStart(string testString);
5 // 实例化委托, 调用的方法需与委托有相同的参数、返回值
6 MyDelegate delegate = new MyDelegate(GetStart);
2、事件(Event)
概念: 当某个类(发布者 Publisher)的某些特定状态改变时,发送通知给所有关心它这个变化的其它类(订阅者 Subscriber),并触发相关类中的相关函数。如按键、点击等都是事件。
发布者: 决定什么时候触发事件。包含事件与委托的定义与声明,执行绑定了事件的方法(订阅者类中方法)。
订阅者: 决定做什么事(提供具体方法)。 接受事件并提供事件处理程序的对象。
事件声明:
1 // 先声明事件的委托类型, 事件在生成时会调用委托
2 public delegate void MyDelegateEventHandler(object sender, EventArgs e);
3 public event MyDelegateEventHandler MyEvent;
二、事件在观察者模式中的应用
举一个《Head First 设计模式》 上的经典应用,附件上有完整的代码。
需求如下: 建立一个气象观测站,该气象站建立在 WeatherData 对象上, 由 WeatherData 对象负责追踪目前的天气状况(温度、湿度、气压)。我们要建立一个应用,有三种(或更多)布告板, 分别显示目前的状况、气象统计以及简单的预报。当 WeatherDataObject 对象获得最新的测量数据时, 三种布告板必须实时更新。并且希望这个气象站的扩展性良好。
1、创建发布者类
1 // 发布者类
2 public class WeatherData
3 {
4 // 声明事件
5 public delegate void WeatherChangeEventHandler(object sender, WeatherChangeArgs e);
6 public event WeatherChangeEventHandler WeatherChange;
7
8 // 虚函数,使得派生类可重写触发事件的标准
9 protected virtual void onWeatherChange(WeatherChangeArgs e)
10 {
11 WeatherChange?.Invoke(this, e);
12 }
13 // 事件一定要在方法中执行
14 public void RaiseWeatherChange(WeatherChangeArgs e)
15 {
16 onWeatherChange(e);
17 }
18 }
19
20 // 创建一个事件类, 提供我们关心的数据的值
21 public class WeatherChangeArgs : EventArgs
22 {
23 public readonly double temperature;
24 public readonly double humidity;
25 public readonly double pressure;
26 public WeatherChangeArgs(double temperature, double humidity, double pressure)
27 {
28 this.temperature = temperature;
29 this.humidity = humidity;
30 this.pressure = pressure;
31 }
32 }
2、创建订阅者类
订阅者数量众多,为了统一管理,需创建一个统一的接口,这也符合 OO 的原则, 面向接口编程。
1 // 创建订阅者统一接口
2 public interface IWeatherStationSubject
3 {
4 void Display(object sender, WeatherChangeArgs e);
5 }
6
7 // 当前状况显示面板
8 public class CurrentConditionDisplay : IWeatherStationSubject
9 {
10 public void Display(object sender, WeatherChangeArgs e)
11 {
12 Console.WriteLine("Current conditons:" + e.temperature + "degreees and " + e.humidity + "% humidity" );
13 }
14 }
15 // 未来预测天气状况显示面板
16 public class ForecastDisplay : IWeatherStationSubject
17 {
18 public void Display(object sender, WeatherChangeArgs e)
19 {
20 Console.WriteLine("Tomorrow weather condition: " + e.temperature*1.1 + " degree ," + e.humidity*0.9 + "% humidity");
21 }
22 }
23
24 // 个人情绪状态预测
25 public class ForecastDisplay : IWeatherStationSubject
26 {
27 public void Display(object sender, WeatherChangeArgs e)
28 {
29 Console.WriteLine("Tomorrow weather condition: " + e.temperature*1.1 + " degree ," + e.humidity*0.9 + "% humidity");
30 }
31 }
3、为了实现订阅系统与主控制系统松耦合, 创建订阅系统
1 public class WeatherSubscriberSystem
2 {
3 public WeatherSubscriberSystem(WeatherData weatherData, WeatherChangeArgs e)
4 {
5 weatherData.WeatherChange += new WeatherData.WeatherChangeEventHandler((new CurrentConditionDisplay()).Display);
6 weatherData.WeatherChange += (new ForecastDisplay()).Display;
7 weatherData.WeatherChange += (new FeelingToneDisplay()).Display;
8 weatherData.RaiseWeatherChange(e);
9 }
4、 主控制系统
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 WeatherSubscriberSystem sys_1 = new WeatherSubscriberSystem(new WeatherData(), new WeatherChangeArgs(20, 18.6, 55));
6 Console.WriteLine("\n");
7 WeatherSubscriberSystem sys_2 = new WeatherSubscriberSystem(new WeatherData(), new WeatherChangeArgs(35, 24, 38));
8 Console.ReadKey();
9 }
10 }
至此整个系统完成了。我们可以发现,用 .net 内置的事件来实现观察者模式,比自己实现更简单,控制起来也更方便。
参考:http://www.cnblogs.com/wudiwushen/archive/2010/04/21/1717378.html