专栏首页yl 成长笔记设计模式(2):观察者模式-2 (委托、事件)

设计模式(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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 装饰器模式

    用户2434869
  • 用命令模式实现撤销与恢复 命令模式定义撤销与重做功能就此实现。整个过程中,最关键部分是命令对象的封装以及控制类与具体工厂类耦合的解除。

    通过 ICommand 接口,实现了控制类与调用者的解耦。 * 下面通过一个简单的实例来详细说明这种解耦以恢复撤销是如何实现。 假定有一个风扇,当前有...

    用户2434869
  • 策略模式及其与简单工厂模式的区别

    The strategy pattern(also known as the policy pattern) is a behavioural software...

    用户2434869
  • DDD设计中的Unitwork与DomainEvent如何相容?

    最近在开发过程中,遇到了一个场景,甚是棘手,在这里分享一下。希望大家脑洞大开一起来想一下解决思路。鄙人也想了一个方案拿出来和大家一起探讨一下是否合理。

    Zachary_ZF
  • 10(01)总结形式参数,包,修饰符,内部类

    类,抽象类,接口的综合小练习 /* 教练和运动员案例(学生分析然后讲解) 乒乓球运动员和篮球运动员。 乒乓球教练和篮球教练。 为了出国交流,跟乒乓球相关...

    奋斗蒙
  • 设计模式-门面模式

    cwl_java
  • 设计模式详解

    需要说明的一点是,文中的 UML 类图和规范的 UML 类图不大相同,其中组合关系使用以下箭头表示:

    琯琯
  • [设计模式] 命令模式

    假定我们定义一个宏命令实现回家后的一个智能操作:包含开灯和开电视,并要求它支持撤销能力。

    架构探险之道
  • Java内功心法,行为型设计模式

    使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。

    李红
  • 23种设计模式详解(三)

    南风

扫码关注云+社区

领取腾讯云代金券