观察者模式

简介

体现了著名好莱坞法则,即: 留下联系方式(subscribe), 不要调用我们,我们会调用你(publish)。

观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

####使用观察者模式的好处: ####

  • 支持简单的广播通信,自动通知所有已经订阅过的对象。
  • 页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
  • 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
  • 可以动态的增加或删除一个订阅者。

代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

(function(win, undefined) {

function Observer(){
this._events = { };
}

Observer.prototype = {
_getEventByName : function( name ){
return ( this._events[ name ] ) || ( this._events[ name ] = [] );
},
_delEventByFunName : function( name, funName){
var eventsArr = this._getEventByName( name );

if( eventsArr.length === 0) {return;}

var poi = eventsArr.indexOf( funName );
if( poi > -1 ){
eventsArr.splice(poi,1);
}
},
// add a subscriber
on : function( name, func ){
this._getEventByName( name ).push( func );
},
// publish, notify all subscriber
fire : function( name ){
var eventsArr = this._getEventByName( name );
if( eventsArr.length === 0 ){ return;}
var args = [].slice.call( arguments,1 );
for (var i = 0, j = eventsArr.length; i < j; i++) {
eventsArr[ i ].apply( this, args );
};
},
// unsubscribe
ubind : function( name, func ){
if( arguments.length === 1){
delete this._events[ name ];
return;
}
this._delEventByFunName( name,func )
}
}
window.Observer = Observer;
})(window);

以下是demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input id="fire" type="button" value="clickMe">
</body>
<script src="scripts/observer/observer.js"></script>
<script>
var f = new Observer();
f.on('click', function(a, b){
console.log('uName: ' + (a* b))
});

var real = function(a,b){
console.log('real : ' + (a + b))
}

var finished = function(a,b){
console.log('finished')
};
f.on('click', real);
f.on('click',finished)

f.ubind('click',real);
var ele = document.getElementById('fire');
ele.addEventListener('click',function(e){
f.fire('click',100,25);
});

</script>
</html>

result

uName: 2500
finished

总结

观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。

总的来说,观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。