前言
委托:
委托是一种在对象里保存方法引用的类型,同时也是一种类型安全的函数指针。
或委托可以看成一种表示函数的数据类型,类似函数指针.
事件是特殊的委托
观察者模式:
两种角色:
(1)Subject, 主题(被监视对象),它往往包含着 Observer 所感兴趣的内容。
(2)Observer, 观察者,它观察 Subject。 当 Subject 中的某件事发生的时候(通常是它所感兴趣的内容改变的时候),会被自动告知,而 Observer 则会采取相应的行动(通常为更新自身状态或者显示输出)。
1、Observer观察者模式:两种身份即监视者和被监视者,是一对多的关系。
(1)被监视者即委托事件的发布者也就是定义委托事件的一方。
(2)监视者即委托事件的订阅者。
2、编码规范:
(1)委托类型的名称都应该以EventHandler结束;
(2)委托的原型定义有一个void返回值,并接受两个输入参数,一个是Object,另一个是EventArgs类型(或继承自EventArgs)。
(3)事件的命名为委托去掉EventHandler之后剩余的部分。
(4)继承自EventArgs的类型应该以EventArgs结尾。
3、简单以“热水器加热水,水温大于95度时报警器响起,显示器显示水温”为例。
Code:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace dotNet之美__委托与事件__Observer观察者模式2 7 { 8 /// <summary> 9 /// 此例子是:热水器加热水,水温大于95度时报警器响起,显示器显示水温。 10 /// </summary> 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 Heater heater = new Heater(); 16 //订阅事件 17 heater.Boiled += new Alarm().AlarmAlert; 18 heater.Boiled += new Display().ShowMsg; 19 //也可以这样订阅 20 heater.Boiled += new Heater.BoiledEventHandler(new Alarm().AlarmAlert); 21 heater.BoilWater(); 22 Console.ReadLine(); 23 } 24 } 25 /// <summary> 26 /// 委托与事件实现:观察者设计模式(两种角色:监视者和被监视者) 27 /// </summary> 28 class Heater//被监视者(委托事件发布者) 29 { 30 //定义订阅者感兴趣的信息,比如:水温、热水器类型以及产地 31 //定义水温 32 private int temperature; 33 //热水器类型 34 public string type = "ReadFire 001"; 35 //产地 36 public string area = "China Guangzhou"; 37 /// <summary> 38 /// 声明一个委托类型 39 /// </summary> 40 /// <param name="sender">发布者对象</param> 41 /// <param name="e">订阅者感兴趣的信息参数</param> 42 public delegate void BoiledEventHandler(Object sender,BoiledEventArgs e); 43 /// <summary> 44 /// 定义委托事件 45 /// </summary> 46 public event BoiledEventHandler Boiled; 47 /// <summary> 48 /// 订阅者感兴趣的信息 49 /// </summary> 50 public class BoiledEventArgs : EventArgs 51 { 52 public readonly int temperature; 53 public BoiledEventArgs(int temperature) 54 { 55 this.temperature = temperature; 56 } 57 } 58 /// <summary> 59 /// 触发的事件 60 /// </summary> 61 /// <param name="e"></param> 62 public void OnBoiled(BoiledEventArgs e) 63 { 64 if (Boiled != null) 65 { 66 Boiled(this, e); 67 } 68 } 69 /// <summary> 70 /// 触发动作 71 /// </summary> 72 public void BoilWater() 73 { 74 for (int i = 0; i <= 100; i++) 75 { 76 this.temperature = i; 77 if (this.temperature > 95) 78 { 79 BoiledEventArgs e = new BoiledEventArgs(this.temperature); 80 OnBoiled(e); 81 } 82 } 83 } 84 } 85 /// <summary> 86 /// 订阅者 87 /// </summary> 88 class Alarm 89 { 90 /// <summary> 91 /// 报警 92 /// </summary> 93 /// <param name="sender">发布者即被监视者对象</param> 94 /// <param name="e">感兴趣的信息</param> 95 public void AlarmAlert(Object sender, Heater.BoiledEventArgs e) 96 { 97 Heater heater = (Heater)sender; 98 Console.WriteLine("Alarm:{0}-{1}", heater.area, heater.type); 99 Console.WriteLine("Alarm:嘀嘀嘀···水温:" + e.temperature); 100 } 101 } 102 /// <summary> 103 /// 订阅者 104 /// </summary> 105 class Display 106 { 107 /// <summary> 108 /// 显示温度 109 /// </summary> 110 /// <param name="sender">发布者即被监视者对象</param> 111 /// <param name="e">感兴趣的信息</param> 112 public void ShowMsg(Object sender, Heater.BoiledEventArgs e) 113 { 114 Heater heater = (Heater)sender; 115 Console.WriteLine("Display:{0}-{1}", heater.area, heater.type); 116 Console.WriteLine("水快被烧开了,水温:" + e.temperature); 117 } 118 } 119 }
运行结果: