一: 基本概念
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(" "); 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