【设计模式】观察者模式

观察者模式

观察者模式是一种基于事件和响应的设计模式,常常用于传统的窗体应用程序以及游戏开发领域。一个典型的场景是,在游戏操作界面中,存在游戏角色、陷阱、怪物、宝物等,当游戏角色移动到陷阱、怪物、宝物的位置时,如何让这个移动事件能够被感知到,并作出正确响应呢?

传统的思路是,陷阱、怪物、宝物周期性地对自己的有效范围进行检测,当检测到主角时则作出响应。这种是“拉取”的思想,但存在明显的弊端,如果事件没有发生,那么程序就会一直“空转”,浪费资源;而且,即便事件有发生,如果检测周期太长,也无法得到实时的响应。

如果换成“推送”的思想,也就是把陷阱、怪物、宝物当做角色的成员变量,每当角色进入有效范围时,则调用相应对象的方法。虽然这种方式把定时“拉取”变成了实时”推送",但又引入了新问题。一是在现实意义上,陷阱、怪物、宝物并不属于游戏角色的属性,把他们当做成员变量并不恰当;二是游戏中肯定不会只有这三个元素,随着游戏内容的丰富,增加的新元素数量会越来越多,这样每次都需要往游戏角色的类添加新的成员变量,明显增加的耦合。

UML 设计

因此,采用观察者模式就能减少代码的耦合,保证对象的抽象性。具体设计包括:

  • 抽象出了一个观察者接口 Observer,所有需要接收事件并作出响应的类,都需要实现这个接口。
  • 被观察对象 Subject,作为一个事件发起者,维护一个观察者列表,可注册新的观察者,或者去掉旧的观察者。

观察者模式的 UML 图为:

img

观察者模式的 UML 图主要有两组实体对象,观察者和被观察者。观察者实现了 Observer 接口,被观察者继承自 Subject 抽象类。

Subject 抽象类依赖抽象的 Observer 接口,避免了观察者与被观察者之间的紧耦合。在 Subject 类中有一个成员变量 ObserverList,存储着已经注册的观察者,当事件发生时,就会通知列表中的所有观察者,进行各自的响应。

public interface Observer {
    public void update();
}

abstract public class Subject {
    private List<Observer> observerList = new ArrayList<Observer>();

    public void attachObserver(Observer observer) {
        observerList.add(observer);
    }

    public void detachObserver(Observer observer){
        observerList.remove(observer);
    }

    public void notifyObservers(){
        for (Observer observer: observerList){
            observer.update();
        }
    }
}

游戏中的陷阱、怪物、宝物对应着 UML 图里的 ConcreteObserver 类,他们各自实现了 Observer 的接口,每一个具体的观察者都有各自的响应方法,作为事件触发的回调方法。

通俗的理解就是,游戏元素作为观察者,检测到游戏角色进入有效范围后,向被观察者(角色)进行注册,等待时间通知;被观察者执行某个动作后,则向事件对应的观察者发送通知,进行回调。

常见应用

许多游戏引擎的底层都使用了观察者模式,比如 Unity3D、Cocos2D。Spring 框架的 ApplicationListener 和 ApplicationContext 两个接口以及它们的实现类也用到了观察者模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值