DOTA中的设计模式(2):观察者模式

 

 

一、概念

观察者模式Strategy):定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。(原文:The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

 

二、类图

 

三、存储记忆:在你的大脑里记下类图,同时理解以下对象的职责与行为

     (1)Subject(被观察的对象接口) 

             a.  规定ConcreteSubject的统一接口;

             b.  每个Subject可以有多个Observer;

     (2)ConcreteSubject(具体被观察对象)

             a.  维护对所有具体观察者的引用的列表;

             b.  状态发生变化时会发送通知给所有注册的观察者。

      (3)Observer(观察者接口)

             a.  规定ConcreteObserver的统一接口;

             b.  定义了一个update()方法,在被观察对象状态改变时会被调用。

      (4)ConcreteObserver(具体观察者)

             a.  维护一个对ConcreteSubject的引用;

             b.  特定状态与ConcreteSubject同步;

             c.  实现Observer接口,通过update()方法接收ConcreteSubject的通知。

    

四、DOTA游戏

(1)在这款游戏中,观察者模式到处都可以找到例子。比如说,我们使用了火枪哥,由于对线作战挣钱比较困难,火枪哥毅然决然的选择了“打野怪”赚点外快!

 (2)火枪哥发起了对“野怪们”的攻击,野怪们发现了有个不要命的家伙在打他们,于是进行了反击!火枪哥被围殴了,发现自己的血量已经被野怪干到了300,不行了,赶紧跑吧,于是野怪们也停止了想这个家伙的攻击,在自己的领地内继续快乐的生活O(∩_∩)O~,这是一个典型的观察者模式,我们一起看看如何实现:

                                    类图,暂略。随后补上...

 

(3)在这个模型中,野怪们是作为观察者:谁打我们,我们打谁,我们观察者的接口设计如下:

  

(4)我们设计了具体的观察者对象:野怪(狗头人,食人魔)。由于我们的野怪具有一些公共的属性,因此我们设计了一个野怪的抽象类:

  野怪抽象类:

  狗头人:

  食人魔:

  (5)有了观察者,就 需要有被观察者对象。在这个模型中,英雄去打野,野怪发现有英雄打他们,就发起反击。所以,这里英雄是作为被观察者的,我们先设计了一个被观察者对象的接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/// <summary>
/// 被观察者:英雄
/// </summary>
public interface ISubjectHero
{
    #region ==== 接口实现 ====
 
    /// <summary>
    /// 注册观察者
    /// </summary>
    /// <param name="observer">观察者</param>
    void RegisterObserver(IObserverMonster observer);
 
    /// <summary>
    /// 移除观察者
    /// </summary>
    /// <param name="observer">观察者</param>
    void RemoveObserver(IObserverMonster observer);
 
    /// <summary>
    /// 通知观察者
    /// </summary>
    void NotifyObserver();
 
    #endregion

  (6)我们设计了一个英雄抽象类,并实现该接口:

  (7)我们创建了一个英雄,火枪哥:

  (8)nice,我们已经成功构建了观察者模型,好,我们开始玩游戏吧,来测试下:

       测试程序:

  测试结果:

      (9)以上我们通过观察者模式实现了这个游戏,在.NET里,我们可以通过事件委托来实现相应功能,留给读者思考。

五、应用场景和优缺点

    (1) 应用场景              

             a.  对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。

             b.  对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

    (2) 优缺点

             a.  SubjectObserver之间是松偶合的,分别可以各自独立改变[优点]

         b. Subject在发送广播通知的时候,无须指定具体的ObserverObserver可以自己决定是否要订阅Subject的通知[优点]

         c. 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合[优点]

         d. 松偶合导致代码关系不明显,有时可能难以理解[缺点]

         e. 如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题[缺点]

 

源代码下载

 

零之轨迹博客:天空之城

作者:何健东
出处:http://traxex.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2012-07-17 20:56  hktkhhhh  阅读(448)  评论(0)    收藏  举报