代码在迭代之后,功能会变得越来越复杂,对于代码的可读性和可扩展性要求也更高。
对于一些底层的功能或复杂的模块,可以通过事件机制达到业务解耦,在关键逻辑中广播事件。这样不需要关心后续的处理,可以提高代码的扩展性,从而达到然有序地开发~

在设计模式里,这称之为观察者模式,扩展阅读:
https://www.runoob.com/design-pattern/observer-pattern.html
类图:

举个例子,游戏中玩家获得一个物品的时候,我们可能需要这样几个逻辑:
a. 在物品模块中,弹出一个提示框:恭喜你获得了X物品
b. 在红点模块中,判断这个物品的属性,如果比当前装备的物品属性好,则增加一个小红点提示
c. 在提示模块中,增加一条日志记录行为,便于排查和定位问题

假设这个需求中,物品模块是铃兰开发的,提示模块是兔兔开发的,红点模块是小碎晶开发的,在没有引入事件机制前,我们的代码大概是这样:

//铃兰写的代码,获得了一个新的物品
function getNewItem(){
//调用铃兰写的提示模块的方法
tips.show(“恭喜获得了一个物品X”);
//调用小碎晶写的红点模块
redDot.check(“item”);
//调用兔兔写的日志模块
log.add(“事件:获得物品,账号:小可爱,时间:202x-2-33 23:33:33”);
}
虽然正确实现了需求,但是这样的做法会存在一些问题:

  1. 程序写功能的时候,需要三只互相沟通,问清楚方法叫什么,参数是什么
  2. 写完测试完毕后,某一天铃兰修改了自己的提示模块的方法名或参数,那兔兔也需要来修改自己的代码,否则会报错
  3. 程序是逐行执行的,如果小碎晶的红点模块代码不够健壮报错了,会导致接下来的log.add也没法正常执行

总的来说,这几个功能的耦合性太高,极有可能验收通过后,某一天突然又不正常惹。

我们考虑观察者机制,设有一命名空间Ob内的方法为观察者模式方法,emit为通知者(广播者)方法,obs为观察者方法,就会产生类似这样的代码:

//小碎晶写的代码,在x.js文件里,获得了一个新的物品
function getNewItem(){
//广播1个事件,事件的名称是 newItem
//事件的内容是:{itemid:物品编号,num:数量}
//小碎晶不用管其他人的代码
Ob.emit(“newItem”,{
itemid:123,
num:2
});
}
//==========================================
//铃兰写的代码,在y.js文件里
Ob.obs(“newitem”,function(itemData){
//监听1个事件,当发生这个事件时候,需要做什么
tips.show(“恭喜你获得了一个物品AAA”);
});
//==========================================
//兔兔写的代码,在z.js文件里
Ob.obs(“newitem”,function(itemData){
//监听1个事件,当发生这个事件时候,需要做什么
redDot.check(“item”);
});
//==========================================
//咕咕写的代码,在w.js文件里
Ob.obs(“newitem”,function(itemData){
//监听1个事件,当发生这个事件时候,需要做什么
log.add(“事件:获得物品,账号:小可爱,时间:202x-2-33 23:33:33”);
});
把一个来回穿插调用的逻辑,拆解到了4个不同的文件里,分别由4个程序员维护自己的代码(解耦),并且当某个成员的逻辑报错的时候,并不会影响其他人的代码。
以上假设Ob方法的用法如下:

//监听1个事件,每次收到这个事件的广播时,都会执行对应functoin里的逻辑
Ob.obs(“事件名”,function(args){
//do something..
//args为广播时发送过来的参数
})
//广播一个事件,可带上一个特定的参数
Ob.emit(“事件名”,”事件参数”)