啥叫观察者模式,我的理解就是,在战场上我看见敌军发射一枚炮弹,我告诉我的士兵卧倒,我就是一个观察者。又好比现在的狙击手,身边都有一个观察者,具体叫啥不知道,反正人家发现敌人了,就和狙击手说默默方向有人,打,完咯狙击手就往那个方向打,指哪打哪,这也是观察者的一种运用吧。
// 定义事件 function incident(){ // 想想存放啥事件 this.fight = {}; } incident.prototype={ // 先把打仗的事件放入(订阅模式) on: function (type, handle) { if(!this.fight[type]){ this.fight[type] = []; } this.fight[type].push(handle); }, // 开始干仗了 emit: function () { // 来获取观察者看到的事件 let type = Array.prototype.shift.call(arguments); // console.log(type,'我看到炮弹了!!') // 判断不是个方法直接干掉(发布假情报的干掉) if(!this.fight[type]){ return false; } // 看到有几个方法,执行几个 for (let i = 0; i < this.fight[type].length; i++) { let handle = this.fight[type][i]; //执行事件 handle.apply(this, arguments); } }, //需要说明的是Array.prototype.shift.call(arguments)这句代码,arguments对象是function的内置对象,可以获取到调用该方法时传入的实参数组。 // shift方法取出数组中的第一个参数,就是type类型。 // 打完仗后 off: function (type, handle) { // 取消掉哪一个观察者 fight = this.fight[type]; // 判断有观察者 if(fight){ // 没方法直接置空数组 if(!handle){ fight.length = 0;//清空数组 }else{ console.log(fight.length) // 把多个方法删除掉其中一个 for (let i = 0; i < fight.length; i++) { let _handle = fight[i]; if(_handle === handle){ fight.splice(i,1); } } } } } } let p1 = new incident(); p1.on('打仗了', function (name) { console.log('打仗了: '+ name); }); p1.emit('打仗了','我知道了'); // console.log('==============='); let p2 = new incident(); let fn = function (name) { console.log('炮弹来了: '+ name); }; let fn2 = function (name) { console.log('前方有敌人: '+ name); }; p2.on('炮弹来了', fn); p2.on('前方有敌人', fn2); p2.emit('炮弹来了','卧槽,卧倒'); p2.emit('前方有敌人','在哪,我没看到啊!'); // console.log('==============='); p2.off('炮弹来了', fn); p2.emit('炮弹来了','我不干了');
总结(1):
它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。
使用观察者模式的好处:
- 支持简单的广播通信,自动通知所有已经订阅过的对象。
- 页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
- 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
总结(自结):
观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
总的来说,观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。