韬光养晦

胸无大志、养家糊口而已!

博客园 首页 联系 订阅 管理

观察者模式是设计模式中行为模型的一种,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
典型的应用情形为:
夜里有一只猫大叫了一声,同处一屋的老鼠接受到了猫大叫的信息,于是开始逃跑。同样,主人听到了,被吵醒了;小孩子听到了,被吓哭了。
实现代码如下:


  1using System;
  2
  3namespace DelegateEvent
  4
  5{
  6
  7    /// <summary>
  8
  9    /// Subject 的摘要说明。
 10
 11    /// 被观察者抽象基类
 12
 13    /// 所有被观察者对象都继承此类
 14
 15    /// 做为抽象基类,此类不允许直接进行实例化
 16
 17    /// 此类中首先定义委托
 18
 19    /// 再有委托定义事件
 20
 21    /// 然后创立与委托想关联的方法Notify
 22
 23    /// </summary>

 24
 25    public abstract class Subject
 26
 27    {
 28
 29        public Subject()
 30
 31        {
 32
 33            //
 34
 35            // TODO: 在此处添加构造函数逻辑
 36
 37            //
 38
 39        }

 40
 41        /// <summary>
 42
 43        /// 创建一个委托
 44
 45        /// </summary>

 46
 47        public delegate void SubEventHandler();
 48
 49        /// <summary>
 50
 51        /// 根据SubEventHandler创建一个事件
 52
 53        /// </summary>

 54
 55        public event SubEventHandler SubEvent;
 56
 57        /// <summary>
 58
 59        /// 将于委托相连接的方法
 60
 61        /// </summary>

 62
 63        protected void Notify()
 64
 65        {
 66
 67            if(this.SubEvent!=null)
 68
 69                this.SubEvent();
 70
 71        }

 72
 73    }

 74
 75}

 76
 77//------------------------------------------------------------------------------------------
 78
 79被观察者基类完成后我们再来创建观察者基类Observer.
 80
 81namespace DelegateEvent
 82
 83{
 84
 85    /// <summary>
 86
 87    /// Observer 的摘要说明。
 88
 89    /// 观察者抽象基类
 90
 91    /// 所有观察者对象都由此类派生
 92
 93    /// 使用此类进行对事件的注册
 94
 95    /// 并和事件的方法关联
 96
 97    /// 另外定义了一个抽象方法Response
 98
 99    /// 可以由子类来进行覆盖
100
101    /// </summary>

102
103    public abstract class Observer
104
105    {
106
107        public Observer(Subject childModel)
108
109        {
110
111            //注册SubEvent事件通过SubEventHandler委托和Response方法关联
112
113            //子类通过调用此构造函数完成事件的注册
114
115            childModel.SubEvent+=new Subject.SubEventHandler(Response);
116
117        }

118
119 
120
121        /// <summary>
122
123        /// 抽象方法,用于引发事件
124
125        /// </summary>

126
127        public abstract void Response();
128
129    }

130
131}

132
133同理,我们还可以继续创建另一个观察者基类,用来响应不同的事件的方法。
134
135namespace DelegateEvent
136
137{
138
139    /// <summary>
140
141    /// Observer2 的摘要说明。
142
143    /// 注册了两个事件的方法。
144
145    /// </summary>

146
147    public abstract class Observer2
148
149    {
150
151        public Observer2(Subject childModel)
152
153        {
154
155            childModel.SubEvent+=new Subject.SubEventHandler(Response);
156
157            childModel.SubEvent+=new Subject.SubEventHandler(Response2);
158
159        }

160
161        public abstract void Response();
162
163        public abstract void Response2();
164
165    }

166
167}

168
169//-------------------------------------------------------------------------------------------------------
170
171现在,我们来针对这个实例中的猫大叫这个引发事件进行解析。
172
173namespace DelegateEvent
174
175{
176
177    /// <summary>
178
179    /// Cat 的摘要说明。
180
181    /// 此类作为被观察者对象
182
183    /// 直接继承Subject类
184
185    /// 使用一个Cry方法,调用Notify方法起用先前定义的SubEvent事件
186
187    /// </summary>

188
189    public class Cat:Subject
190
191    {
192
193        public Cat()
194
195        {
196
197            //
198
199            // TODO: 在此处添加构造函数逻辑
200
201            //
202
203        }

204
205        public void Cry()
206
207        {
208
209            System.Console.WriteLine("Cat Cry..");
210
211            //调用从ModelBase继承过来的Notify()
212
213            this.Notify();          
214
215        }

216
217    }

218
219}

220
221// 这样一个被观察者对象就完成了。
222
223//--------------------------------------------------------------------------------------------------------------------
224
225被观察者对象有了,我们再来创建具体的观察者对象。此例中,有主人,小孩和老鼠对猫的叫声做出了反应,因此我们可以创建三个类,分别对主人、小孩和老鼠进行响应。其中,主人和老鼠对应Observer类,响应其中的一个事件;而小孩则继承Observer2类,响应其中的两个事件。
226
227//------------------------------------观察者--主人类---------------------------------------------------
228
229namespace DelegateEvent
230
231{
232
233    /// <summary>
234
235    /// Master 的摘要说明。
236
237    /// </summary>

238
239    public class Master:Observer
240
241    {
242
243        /// <summary>
244
245        /// 构造函数,接受一个Cat类型的对象childModel并强制转换为基类ModelBase变量
246
247        /// 再将childModel传入到父类Observer的构造函数当中,实现注册。
248
249        /// </summary>
250
251        /// <param name="childModel"></param>

252
253        public Master(Subject childModel):base(childModel)
254
255        {       
256
257            
258
259        }

260
261        public override void Response()
262
263        {
264
265            System.Console.WriteLine("主人醒来");
266
267        }

268
269    }

270
271}

272
273//------------------------------------观察者--老鼠类-----------------------------------------------------
274
275namespace DelegateEvent
276
277{
278
279    /// <summary>
280
281    /// Mouse 的摘要说明。
282
283    /// </summary>

284
285    public class Mouse:Observer
286
287    {
288
289        private string name;
290
291        public Mouse(string name, Subject childModel):base(childModel)
292
293        {
294
295            this.name=name;         
296
297        }

298
299 
300
301        //覆盖Observer类Response方法
302
303        public override void Response()
304
305        {
306
307            System.Console.WriteLine(this.name+"开始逃跑");
308
309        }

310
311    }

312
313}

314
315//于主人类不同的是,老鼠类的构造函数可以接受一个字符串参数,这样可以变的更多样化
316
317//------------------------------------观察者--小孩------------------------------------------------------------
318
319namespace DelegateEvent
320
321{
322
323    /// <summary>
324
325    /// Child 的摘要说明。
326
327    /// </summary>

328
329    public class Child:Observer2
330
331    {
332
333        public Child(Subject childBase):base(childBase)
334
335        {
336
337 
338
339        }

340
341        public override void Response()
342
343        {
344
345            Console.WriteLine("baby醒来。。。。");
346
347        }

348
349        public override void Response2()
350
351        {
352
353            Console.WriteLine("开始哭闹。。。。。");
354
355        }

356
357    }

358
359}

360
361//小孩类里,由于继承的是Observer2类,因此可以响应两种不同的方法。
362
363在主函数里,定义每个观察者子类的对象,由其构造函数接受被观察者对象进行事件的响应。
364
365namespace DelegateEvent
366
367{
368
369    /// <summary>
370
371    /// SubMain 的摘要说明。
372
373    /// </summary>

374
375    public class SubMain
376
377    {
378
379        public SubMain()
380
381        {
382
383            
384
385        }

386
387        /// <summary>
388
389        /// 主函数,定义子类对象
390
391        /// </summary>

392
393        public static void Main()
394
395        {
396
397            Cat myCat=new Cat();
398
399            Mouse myMouse1=new Mouse("mouse1",myCat);
400
401            Mouse myMouse2=new Mouse("mouse2",myCat);
402
403            Master myMaster=new Master(myCat);
404
405            
406
407            Child myLittleMaster=new Child(myCat);
408
409            myCat.Cry();
410
411        }

412
413    }

414
415}

416
417

改变一下应用环境:
老鼠偷油,猫来捉老鼠,老鼠吓跑,打碎了油瓶,人被吵醒。
这样的一个环境下,如何使用观察者模式呢?
首先区分,谁是一整串事件的引发者,可以分析是老鼠,老鼠偷油这件事情引发了一系列事件。
猫作为老鼠的观察者,当老鼠偷油这件事情发生以后,触发猫捉老鼠的事件,而下面思维开始混乱,因为老鼠逃跑,打翻油瓶这件事按理论来说应该不是直接由老鼠偷油这件事情引发的,而是由猫捉老鼠这件事情。因此在猫捉老鼠,老鼠逃跑的事件中,又似乎是猫是被观察者,而老鼠是观察者。但这样理解的话,是不是就形成一种循环了亚。
但细细想来,上面这个问题又是自欺欺人,因为首先观察者模式是希望实现一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
从上面情形来看,老鼠逃跑只是这个链上的一个节点,而这个节点的事件发起人正是被观察者,因此又出现下列问题,被观察者能否依赖于其本身呢?只要是能依赖,这样一个情形,使用观察者模性就是合理的。但是假使这样可行的话,那么观察者和被观察者之间是否又没有了清晰的界限,加大了对象之间的耦合关系,这是不是又违背OO思想?希望大家给点意见。
上述情形实现代码如下:

  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4
  5namespace ConsoleApplication3
  6{
  7    /// <summary>
  8    /// 被观察者的抽象类
  9    /// </summary>

 10    public class Model
 11    {
 12        /// <summary>
 13        /// 定义一个返回为空的委托
 14        /// </summary>

 15        public delegate void  ModelDelegate();
 16        /// <summary>
 17        /// 通知事件
 18        /// </summary>

 19        event ModelDelegate _notifyEvent;
 20        /// <summary>
 21        /// 通知事件
 22        /// </summary>

 23        public event ModelDelegate NotifyEvent
 24        {
 25            add
 26            {
 27                this._notifyEvent += value;
 28            }

 29            remove
 30            {
 31                this._notifyEvent -= value;
 32            }

 33        }

 34        /// <summary>
 35        /// 通知方法 
 36        /// </summary>

 37        public void Notify()
 38        {
 39            this._notifyEvent();    
 40        }

 41        List<Observer> _observers = new List<Observer>();
 42        /// <summary>
 43        /// 构造
 44        /// </summary>

 45        public Model()
 46        {
 47
 48        }

 49
 50        /// <summary>
 51        /// 观察者集合
 52        /// </summary>

 53        public List<Observer> ObserversCollection
 54        {
 55            get
 56            {
 57                return _observers;
 58            }

 59            set
 60            {
 61                _observers = value;
 62            }

 63        }

 64
 65        /// <summary>
 66        /// 注册观察者
 67        /// </summary>
 68        /// <param name="observer"></param>

 69        public void RegisterObserver(Observer observer)
 70        {
 71            if (observer != null)
 72            {
 73                this.ObserversCollection.Add(observer);
 74            }

 75        }

 76        /// <summary>
 77        /// 注销观察者
 78        /// </summary>
 79        /// <param name="observer"></param>

 80        public void DetachObserver(Observer observer)
 81        {
 82            if (observer != null)
 83            {
 84                this.ObserversCollection.Remove(observer);
 85            }

 86        }
 
 87      
 88    }

 89}

 90
 91
 92
 93using System;
 94using System.Collections.Generic;
 95using System.Text;
 96
 97namespace ConsoleApplication3
 98{
 99    public abstract class Observer
100    {
101        private Model _model;
102
103        #region Contructor 
104        /// <summary>
105        /// 构造函数
106        /// </summary>
107        /// <param name="model"></param>

108        public Observer(Model model)
109        {
110            this._model = model;
111            this._model.NotifyEvent += new Model.ModelDelegate(DoSomeThing);
112        }
       
113        #endregion

114
115
116        #region Public Field
117        /// <summary>
118        /// 被观察者
119        /// </summary>

120        public Model ObserverdModel
121        {
122            get
123            {
124                return _model;
125            }

126            set
127            {
128                _model = value;
129            }

130        }

131        #endregion

132
133        #region Method
134        /// <summary>
135        /// 观察者得到通知后的操作
136        /// </summary>

137        public abstract void DoSomeThing();        
138        #endregion

139    }

140}

141
142
143using System;
144using System.Collections.Generic;
145using System.Text;
146
147namespace ConsoleApplication3
148{
149    public enum RatStateEnmu
150    {
151        Stealing,
152        Running,
153        StrickDownBottom,
154        Tackled
155    }

156    public class Rat:Model
157    {
158        bool _seeCat;
159        RatStateEnmu _state;
160        public RatStateEnmu State
161        {
162            get
163            {
164                return _state;
165            }

166            set
167            {
168                _state = value;
169            }

170        }

171        EventHandler _seeCatHandler;        
172        public event EventHandler SeeCatComming
173        {
174            add
175            {
176                _seeCatHandler += value;
177            }

178            remove
179            {
180                _seeCatHandler -= value;
181            }

182        }

183        void Run(Object sender,EventArgs e)
184        {
185            Console.WriteLine("Rat:不好,大傻猫过来了,赶紧跑!\n");
186            _state = RatStateEnmu.Running;
187            if (_seeCatHandler != null)
188            {
189                _seeCatHandler(sender,e);
190            }

191        }
       
192        /// <summary>
193        /// 是否看见了猫
194        /// </summary>

195        public bool SeeCat
196        {
197            get
198            {
199                return _seeCat;
200            }

201            set
202            {
203                _seeCat = value;
204                Run(thisnew EventArgs());
205            }

206        }

207        public void StealOil()
208        {
209            Console.WriteLine("Rat:噔噔噔噔,我是一只小老鼠,自由的小老鼠,我赛,好大一桶油,够我吃1年的了。我要把它搬回家!\n");
210            Console.WriteLine("Rat:等等,听说最近死猫经常出现,小心点为妙!\n");
211            this._state = RatStateEnmu.Stealing;
212            this.Notify();
213        }

214
215        public void StrickDowmBottle()
216        {
217            Console.WriteLine("system:哗啦啦,油瓶子被打翻了!\n");
218            this._state = RatStateEnmu.StrickDownBottom;
219            this.Notify();
220        }

221    }

222}

223
224
225using System;
226using System.Collections.Generic;
227using System.Text;
228
229namespace ConsoleApplication3
230{
231    /// <summary>
232    /// 观察者-猫
233    /// </summary>

234    public class Cat:Observer
235    {
236        private Rat _rat;
237
238        public Cat(Rat rat) : base(rat)
239        {
240            this._rat = rat;
241            this._rat.SeeCatComming += new EventHandler(_rat_SeeCatComming);
242        }

243
244        void _rat_SeeCatComming(object sender, EventArgs e)
245        {
246            this._rat.StrickDowmBottle();   
247        }

248
249        public override void DoSomeThing()
250        {
251            if (_rat.State== RatStateEnmu.Stealing)
252            {
253                Console.WriteLine("cat:谁打扰了我的美梦,原来是你这个臭老鼠,耽误你猫大爷的休息,我要吃了你!\n");
254                this._rat.SeeCat = true;
255            }

256        }

257    }

258}

259
260
261using System;
262using System.Collections.Generic;
263using System.Text;
264
265namespace ConsoleApplication3
266{
267    public class Person:Observer
268    {
269        Rat rat;
270        public Person(Rat rat)
271            : base(rat)
272        {
273            this.rat = rat;
274            Console.WriteLine("Person:呼噜呼噜,昨天加班到3点,今天睡得真香!\n");
275        }

276        public override void DoSomeThing()
277        {
278            if (rat.State == RatStateEnmu.StrickDownBottom)
279            {
280                Console.WriteLine("Person:这是干什么呢亚,噼哩啪啦的,把我都给吵醒了\n");
281            }

282        }

283    }

284}

285
286--程序入口点
287using System;
288using System.Collections.Generic;
289using System.Text;
290
291namespace ConsoleApplication3
292{
293    class Program
294    {
295        static void Main(string[] args)
296        {
297            Rat rat = new Rat();
298            Person p = new Person(rat);
299            Cat cat = new Cat(rat);
300            rat.StealOil();
301            Console.Read();
302        }

303    }

304}

305
306

    result:


UML关系图:

posted on 2007-03-29 17:36  eric.123  阅读(267)  评论(0)    收藏  举报