Observer设计模式 #region Observer设计模式
  2/**//*
  3 * 假设热水器由三部分组成:热水器、警报器、显示器,它们来自于不同厂商并进行了组装。那么应该是热水器仅仅负责烧水,它不能发出警报也不能显示水温;
  4 * 在水烧开时由警报器发出警报、显示器显示提示和水温。
  5 * 
  6 * Observer设计模式中主要包括如下两类对象:
  7 * (1)Subject: 监视对象,它往往包含着其它对象所感兴趣的内容。在本范例中,热水器就是一个监视对象,它包含的其它对象所感兴趣的内容,就是temprature
  8 *      字段,当这个字段的值快到100时,会不断把数据发给监视它的对象。
  9 * (2)Observer: 监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器
 10 *      和显示器,它们采取的行动分别是发出警报和显示水温。
 11 * 
 12 * 在本例中,事情发生的顺序应该是这样的:
 13 * (1)警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。
 14 * (2)热水器知道后保留对警报器和显示器的引用。
 15 * (3)热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。
 16 * 
 17 * 类似这样的例子是很多的,GOF对它进行了抽象,称为Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的
 18 * 状态改变时,其它依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。
 19 * 
 20 * .Net Framework中的委托与事件
 21 * 尽管上面的范例很好第完成了我们想要完成的工作,但是我们不仅疑惑:为什么.Net Framework中的事件模型与上面的不同?为什么有很多的EventArgs参数?
 22 * 在回答上面的问题之前,我们先搞懂.Net Framework的编码规范:
 23 * (1)委托类型的名称都应该以EventHandler结束。
 24 * (2)委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object类型,一个EventArgs类型(或继承自EventArgs)。
 25 * (3)事件的命名为:委托去掉EventHandler之后剩余的部分。
 26 * (4)继承自EventArgs的类型应该以EventArgs结尾。
 27 * 
 28 * 再做一下说明:
 29 * (1)委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是Heater(热水器)。回调函数(比如 Alarm的MakeAlert)可以通过它
 30 * 访问触发事件的对象(Heater)。
 31 * (2)EventArgs对象包含了Observer所感兴趣的数据,在本例中是temperature。
 32 * 
 33 * 上面这些其实不仅仅是为了编码规范而已,这样也使得程序有更大的灵活性。比如说,我们不光想获得热水器的温度,还想在Observer端(警报器或者显示器)
 34 * 方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得麻烦,而如果我们将热水器的引用传给警报器方法,就可以在方法中直接访问热水器了。
 35 * 
 36 */
 37#endregion
 38  using  System;
 39  using  System.Collections.Generic;
 40  using  System.Text;
 41 
 42  namespace  ObserverMode
 43   {
 44    非Observer设计模式#region 非Observer设计模式
 45    //class Heater
 46    //{
 47    //    private int temperature;
 48        
 49    //    //烧水
 50    //    public void BoilWater()
 51    //    {
 52    //        for (int i = 0; i <= 100; i++)
 53    //        {
 54    //            temperature = i;
 55    //            if (temperature > 95)
 56    //            {
 57    //                MakeAlert(temperature);
 58    //                ShowMsg(temperature);
 59    //            }
 60    //        }
 61    //    }
 62
 63    //    //发出语音警报
 64    //    private void MakeAlert(int param)
 65    //    {
 66    //        Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度了。", param);
 67    //    }
 68
 69    //    //显示水温
 70    //    private void ShowMsg(int param)
 71    //    {
 72    //        Console.WriteLine("Display:水快开了,当前温度:{0}度。", param);
 73    //    }
 74    //}
 75
 76    //class Program
 77    //{
 78    //    static void Main(string[] args)
 79    //    {
 80    //        Heater ht = new Heater();
 81    //        ht.BoilWater();
 82    //        Console.ReadLine();
 83    //    }
 84    //}
 85    #endregion
 86
 87    Observer设计模式#region Observer设计模式
 88
 89    /**/////热水器
 90    //public class Heater
 91    //{
 92    //    private int temperature;
 93    //    public delegate void BoilHandler(int param);    //声明委托
 94    //    public event BoilHandler BoilEvent;             //声明事件
 95        
 96    //    //烧水
 97    //    public void BoilWater()
 98    //    {
 99    //        for (int i = 0; i <= 100; i++)
100    //        {
101    //            temperature = i;
102
103    //            if (temperature > 95)
104    //            {
105    //                if (BoilEvent != null)      //如果有对象注册
106    //                {
107    //                    BoilEvent(temperature); //调用所有注册对象的方法
108    //                }
109    //            }
110    //        }
111    //    }
112    //}
113
114    /**/////警报器
115    //public class Alarm
116    //{
117    //    public void MakeAlert(int param)
118    //    {
119    //        Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度。", param);
120    //    }
121    //}
122
123    /**/////显示器
124    //public class Display
125    //{
126    //    public static void ShowMsg(int param)      //静态方法
127    //    {
128    //        Console.WriteLine("Display:水已烧开,当前温度:{0}度。", param);
129    //    }
130    //}
131
132    //class Program
133    //{
134    //    static void Main(string[] args)
135    //    {
136    //        Heater heater = new Heater();
137    //        Alarm alarm = new Alarm();
138
139    //        heater.BoilEvent += alarm.MakeAlert;                //注册方法
140    //        heater.BoilEvent += (new Alarm()).MakeAlert;        //给匿名对象注册方法
141    //        heater.BoilEvent += Display.ShowMsg;                //注册静态方法
142    //        heater.BoilWater();                                 //烧水,会自动调用注册对象的方法
143    //        Console.ReadLine();
144    //    }
145    //}
146    #endregion
147
148    符合.Net Framework规范的Observer设计模式#region 符合.Net Framework规范的Observer设计模式
149
150    //热水器
151    public class Heater
152    {
153        private int temperature;
154        public string type = "RealFile 001";    //添加型号作为演示
155        public string area = "China Xian";      //添加产地作为演示
156
157        //定义BoiledEventArgs类,传递给Observer所感兴趣的信息
158        public class BoiledEventArgs : EventArgs
159        {
160            public readonly int temperature;
161            public BoiledEventArgs(int temperature)
162            {
163                this.temperature = temperature;
164            }
165        }
166
167        //声明委托
168        public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);
169        public event BoiledEventHandler Boiled; //声明事件
170
171        //可以供继承自Heater的类重写,以便继承类拒绝其它对象对它的监视
172        protected virtual void OnBolied(BoiledEventArgs e)
173        {
174            if (Boiled != null)
175            {
176                Boiled(this, e);
177            }
178        }
179
180        //烧水
181        public void BoilWater()
182        {
183            for (int i = 0; i <= 100; i++)
184            {
185                temperature = i;
186                if (temperature > 95)
187                { 
188                    //建立BoiledEventArgs对象。
189                    BoiledEventArgs e = new BoiledEventArgs(temperature);
190                    OnBolied(e);    //调用OnBoiled方法
191                }
192            }
193        }
194    }
195
196    //警报器
197    public class Alarm
198    {
199        public void MakeAlert(Object sender, Heater.BoiledEventArgs e)
200        {
201            Heater heater = (Heater)sender;
202            //访问sender中的公共字段
203            Console.WriteLine("Alarm:{0} - {1}:", heater.area, heater.type);
204            Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度了:", e.temperature);
205            Console.WriteLine();
206        }
207    }
208
209    //显示器
210    public class Display
211    {
212        public static void ShowMsg(object sender, Heater.BoiledEventArgs e)
213        {
214            Heater heater = (Heater)sender;
215            Console.WriteLine("Display:{0} - {1}:", heater.area, heater.type);
216            Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", e.temperature);
217            Console.WriteLine();
218        }
219    }
220
221    class Program
222    {
223        static void Main(string[] args)
224        {
225            Heater heater = new Heater();
226            Alarm alarm = new Alarm();
227
228            heater.Boiled += alarm.MakeAlert;   //注册方法
229            heater.Boiled += (new Alarm()).MakeAlert;   //给匿名对象注册方法
230            heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert);    //也可以这么注册
231            heater.Boiled += Display.ShowMsg;   //注册静态方法
232            heater.BoilWater();
233            Console.ReadLine();
234        }
235    }
236
237    #endregion
238}
239