观察者模式

      最近,小编重新回顾了百度前端大牛张容铭的《JavaScript设计模式》一书,不得不推荐下这本书,因为讲得实在太精彩了,很生动,可谓是书回价值O(∩_∩)O,玩过Angularjs、Reactjs,Redux,了解过RxJS,实现原理都用到观察者模式,可见其重要性,以下便是我的学习总结~

    观察者模式(Observer): 又称为发布-订阅者模式或者消息机制,主要作用是为了解决类或对象之间的耦合,解耦两个相互依赖的对象,使其依赖观察者的消息机制。适用场景比如团队成员用独立闭包模块进行模块开发,为了避免新模块与旧模块的严重耦合,即可采用观察者模式。

实现思想代码如下,引用自《JavaScript设计模式》一书

 1 var Observer = (function(){
 2     //将消息容器作为静态私有变量存储,是为了防止消息队列暴露而被篡改
 3     var __message = {};
 4     return {
 5         //注册信息接口
 6         regist:function(type,fn){
 7             if(typeof __message[type] === 'undefined'){
 8                 __message[type] = [fn];
 9             }else{
10                 __message[type].push(fn);
11             }
12         },
13         //发布信息接口
14         fire:function(type,args){
15             if(!__message[type])
16                 return;
17             var events = {
18                 type:type,
19                 args:args || {}
20             },
21             i = 0,
22             len = __message[type].length;
23             for(;i < len;i++){
24                 __message[type][i].call(this,events)
25             }
26         },
27         //移除信息接口
28         remove:function(type,fn){
29             if(__message[type] instanceof Array){
30                 var i = __message[type].length - 1;
31                 for(;i > 0;i--){
32                     __message[type][i] === fn && __message[type].splice(i,1);
33                 }
34             }
35         }
36     }
37 })();
38 // 注册接口:将订阅者注册的消息推入消息队列中
39 // 发布接口:当观察者发布一个消息时将所有订阅者订阅的消息一次执行。
40 // 移除接口:将订阅者注销的消息从消息队列中注销

      笔者室友是一位前端大牛,他的博文中也谈到了观察者模式的JS实现,思想是一样但代码实现有点不一样,于是我借用他的demo改造成自己的实现,代码如下:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7 </head>
 8 
 9 <body>
10     <div class="ez-led" id="clock">00:00:00</div>
11 
12     <script type="text/javascript">
13         var Observer = (function(){
14             //将消息容器作为静态私有变量存储,是为了防止消息队列暴露而被篡改
15             var __message = {};
16             return {
17                 //注册信息接口
18                 regist:function(type,fn){
19                     if(typeof __message[type] === 'undefined'){
20                         __message[type] = [fn];
21                     }else{
22                         __message[type].push(fn);
23                     }
24                 },
25                 //发布信息接口
26                 fire:function(type,args){
27                     if(!__message[type])
28                         return;
29                     var events = {
30                         type:type,
31                         args:args || {}
32                     },
33                     i = 0,
34                     len = __message[type].length;
35                     for(;i < len;i++){
36                         __message[type][i].call(this,events)
37                     }
38                 },
39                 //移除信息接口
40                 remove:function(type,fn){
41                     if(__message[type] instanceof Array){
42                         var i = __message[type].length - 1;
43                         for(;i >= 0;i--){
44                             __message[type][i] === fn && __message[type].splice(i,1);
45                         }
46                     }
47                 }
48             }
49         })();
50 
51         window.onload = function() {
52             var elClock = document.getElementById('clock');
53             var getTime = function() {
54                 var _ = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09'], //补零
55                     d = new Date(),
56                     h = d.getHours(),
57                     m = d.getMinutes(),
58                     s = d.getSeconds();
59                 return [_[h] || h, _[m] || m, _[s] || s].join(":");
60             }
61             elClock.textContent = getTime();
62 
63             function renderClock(data){
64                 elClock.textContent = data.args.msg;
65             }
66 
67             //注册渲染时钟消息
68             Observer.regist('renderClockMessage',renderClock)
69 
70             setInterval(function(){
71                 //每隔1s钟,发布渲染时钟消息
72                 Observer.fire('renderClockMessage',{msg:getTime()})
73             },1000)
74         }
75     </script>
76 </body>
77 </html>

参考注明:

  1. 百度前端大牛张容铭《JavaScript设计模式》
  2. 优秀室友博文之《JS实现Observable观察者模式》
原文地址:https://www.cnblogs.com/DTBelieve/p/6374310.html