设计模式(2):观察者模式-2 (委托、事件)

一: 基本概念

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

 

posted on 2017-10-19 13:32  张居斜  阅读(622)  评论(0编辑  收藏  举报

导航