JS 设计模式如此之多,这篇文章就简单的介绍一下订阅发布模式(观察者模式),撇开理论逻辑不说,说一下生活中的事情。经典的示例就是烧水的示例。我们通常在烧水之前都会计划一些事情,我们为什么要烧水,烧完水我们要做什么,比如我们计划三件事情:
1、水开了我要洗脸
2、水开了我要泡面
3、水开了我要给邻居的花浇点水(这个邪恶的想法可以忽视,哈哈)
现在我们计划好了三件事情,然后我们去烧水,水壶放在炉子上烧,我们也不能一直盯着它呀,这个时候我们可以去看电视,听说最近有个叫啥啥啥啥的综艺节目不错,我去瞅瞅,这个时候烧水的事情在进行,同时我也去看电视了,这个过程可以体现出了事件的异步,(事件驱动本事就是异步的),正当我们看的兴起的时候,水壶上面的哨子响了,说明水开了,没办法,很不情愿的去把烧开的水拿过来,想一下,刚开想做三件事来着,于是乎我就用热水洗脸、泡面、浇花去了。
好,到此为止,然后我们结合模式来说一下,我们烧水之前为水开了订阅了三件事情、洗脸、泡面、浇花,然后开始烧,水烧开了时候我就被通知了,被哨子通知了,这样我就可以做我之前订阅(约定)好的事情。这个过程中哨子响了就是发布一个事情,这个时候你就会执行三个事情。分开来讲,烧水、洗脸、泡面、浇花这几个事件之间是没有任何联系的,我烧开水可以干别的事情对吧,只要你订阅好就行。
来点代码试试,首先写一个事件器,包含事件的订阅,发布、取消方法
function EventEmitter() {}; //订阅方法 EventEmitter.prototype.on = function(type, fn) { if (!this["aEmitter" + type]) { this["aEmitter" + type] = []; } var a = this["aEmitter" + type]; for (var i = 0; i < a.length; i++) { if (a[i] == fn) return; } a.push(fn); }; //发布方法 EventEmitter.prototype.run = function(e,systemEvent) { var a = this["aEmitter" + e.type]; if (a) { for (var i = 0; i < a.length; i++) { if (typeof a[i] == "function") { a[i].call(this, e); } else { a.splice(i, 1); i--; } } } }; //取消方法 EventEmitter.prototype.off = function(type, fn) { var a = this["aEmitter" + type]; if (a) { for (var i = 0; i < a.length; i++) { if (a[i] == fn) { a[i] = null; return; } } } }
以上代码是一个事件器,可以使用它来进行事件的发布和订阅、取消。
再写一个类,是我们的主方法
function Kettle() {}; //如果让Kettle具备on,run,off这三个功能,则让Kettle类继承EventEmitter类 Kettle.prototype = new EventEmitter; //会破坏原有的原型引用,慎用,推荐使用Kettle.prototype.__proto__=EventEmitter.prototype,但不兼容 Kettle.prototype.boiling = function() { console.log("水放到火上开始烧了!"); var that = this; setTimeout(function() {//定时器模拟方法运行 console.log("水开啦"); //主行为完成,“通知”应该在这儿完成 that.run({ type: "boiling", message: "水烧开啦!" }); }, 5000); }
我们发布行为的方法也写好了,现在该我们的行为方法了
var obj = new Kettle; //订阅三个方法 obj.on("boiling", wash); obj.on("boiling", drink); obj.on("boiling", flower); //执行发布方法 obj.boiling(); function wash() { console.log('洗脸') }; function drink() { console.log('喝水') }; function flower() { console.log("浇花"); }
到此就应该完成了一个简单的模型了,订阅发布模式是为了将js中的模块进行解耦,避免高耦合的发生,所以在代码设计前要根据自己的项目需求选择合适的模式,观察值模式并不是适合所有,js的设计模式有20多种,各有优点也有弊端,各位君酌情选择。
文章评论