前言
试想这样一个问题,当某个事件发生时,比如在游戏中A模块修改了用户的金币数,而B模块和C模块提供的功能都依赖于用户的金币数,那么,A模块在修改金币数的同时,就需要通知B模块和C模块。常规的方法就是A模块持有B模块和C模块的对象,然后分别通过调用对象接口的方式告诉它们,“嘿,我修改了用户的金币数,改成了10金币”。
但这样就带来了许多问题:
A模块引用了B模块和C模块,耦合严重
A模块修改金币数的方法中调用了B,C模块的方法,当这两个模块发生变化时(比如B模块接收金币数的接口名称改变了,或是C模块不再需要知道金币数改变了),A模块也要修改
当又出现一个D模块也需要知道金币数的变化时,同样需要修改A模块以适应这种需求
为了解决上面的问题,我们自然想到了观察者模式。
观察者模式
这里简单说一下什么是观察者模式:定义对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者(称之为观察者)都会接收到通知并自动更新。
观察者模式的好处是,对象之间是松耦合的,当一个对象改变状态时,它并不需要知道自己的观察者是谁,只需要发布通知即可。任何时候都可以增加或删除观察者,不会影响到发布通知的对象。
而事件分发系统就是观察者模式的一个具体实现
事件分发系统
事件分发系统核心需要提供的功能主要包括以下几个部分:
当一个对象发生改变时,可以认为此时产生了一个事件,提供一个派发事件的接口,以通知所有的观察者
需要提供注册监听事件的接口,以让观察者可以订阅自己需要接收的事件
还需提供反注册监听事件接口,以让观察者可以取消自己的订阅
最好还能在订阅的时候设置优先级,优先级越高的可以越先被通知
使用事件分发系统解决问题
首先,来看看使用事件分发系统处理上面提到的问题,会是什么样的效果。
A模块只需要派发金币修改事件,B,C模块只需要订阅金币修改事件,之后便可以收到通知了。是不是很简单呢
local B = class()
function B:on_money_change( money )
print(money, "B receive event")