龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

大型JavaScript应用程序架构模式(1)(2)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
建议的架构 我们本文的重点来了,这次我们提议的架构使用了我们都很熟知的设计模式:module, facade和mediator。 和传统的模型不一样的是,为了解耦各个模

建议的架构

我们本文的重点来了,这次我们提议的架构使用了我们都很熟知的设计模式:module, facade和mediator。

和传统的模型不一样的是,为了解耦各个模块,我们只让模块发布一些event事件,mediator模式可以负责从这些模块上订阅消息message,然后控制通知的response,facade模式用户限制各模块的权限。

以下是我们要注意讲解的部分:

1 设计模式

1.1 模块论

1.1.1 综述

1.1.2 Module模式

1.1.3 对象自面量

1.1.4 CommonJS模块

1.2 Facade模式

1.3 Mediator模式

2 应用到你的架构

2.1 Facade - 核心抽象

2.2 Mediator - 程序核心

2.3 紧密联合运作起来

模块论

大家可能都或多或少地使用了模块化的代码,模块是一个完整的强健程序架构的一部分,每个模块都是为了单独的目的为创建的,回到Gmail,我们来个例子,chat聊天模块看起来是个单独的一部分,其实它是有很多单独的子模块来构成,例如里面的表情模块其实就是单独的子模块,也被用到了发送邮件的窗口上。

另外一个是模块可以动态加载,删除和替换。

在JavaScript里,我们又几种方式来实现模块,大家熟知的是module模式和对象字面量,如果你已经熟悉这些,请忽略此小节,直接跳到CommonJS部分。

Module模式

module模式是一个比较流行的设计模式,它可以通过大括号封装私有的变量,方法,状态的,通过包装这些内容,一般全局的对象不能直接访问,在这个设计模式里,只返回一个API,其它的内容全部被封装成私有的了。

另外,这个模式和自执行的函数表达式比较相似,唯一的不同是module返回的是对象,而自执行函数表达式返回的是function。

众所周知, JavaScript不想其它语言一样有访问修饰符,不能为每个字段或者方法声明private,public修饰符,那这个模式我们是如何实现的呢?那就是return一个对象,里面包括一些公开的方法,这些方法有能力去调用内部的对象。

看一下,下面的代码,这段代码是一个自执行代码,声明里包括了一个全局的对象basketModule, basket数组是一个私有的,所以你的整个程序是不能访问这个私有数组的,同时我们return了一个对象,其内包含了3个方法(例如addItem,getItemCount,getTotal),这3个方法可以访问私有的basket数组。

  1. var basketModule = (function() {  
  2. var basket = []; //private  
  3. return { //exposed to public  
  4. addItem: function(values) {  
  5. basket.push(values);  
  6. },  
  7. getItemCount: function() {  
  8. return basket.length;  
  9. },  
  10. getTotal: function(){  
  11. var q = this.getItemCount(),p=0;  
  12. while(q--){  
  13. p+= basket[q].price;  
  14. }  
  15. return p;  
  16. }  
  17.  }  
  18. }()); 

同时注意,我们return的对象直接赋值给了basketModule,所以我们可以像下面一样使用:

  1. //basketModule is an object with properties which can also be methods  
  2. basketModule.addItem({item:'bread',price:0.5});  
  3. basketModule.addItem({item:'butter',price:0.3});  
  4.    
  5. console.log(basketModule.getItemCount());  
  6. console.log(basketModule.getTotal());  
  7.    
  8. //however, the following will not work:  
  9. console.log(basketModule.basket);// (undefined as not inside the returned object)  
  10. console.log(basket); //(only exists within the scope of the closure) 

那在各个流行的类库(如Dojo, jQuery)里是如何来做呢?

Dojo

Dojo试图使用dojo.declare来提供class风格的声明方式,我们可以利用它来实现Module模式,例如如果你想再store命名空间下声明basket对象,那么可以这么做:

  1. //traditional way  
  2.   var store = window.store || {};  
  3.   store.basket = store.basket || {};  
  4.      
  5.   //using dojo.setObject  
  6.   dojo.setObject("store.basket.object", (function() {  
  7.   var basket = [];  
  8.   function privateMethod() {  
  9.   console.log(basket);  
  10.   }  
  11.   return {  
  12.   publicMethod: function(){  
  13.   privateMethod();  
  14.   }  
  15.    };  
  16.   }())); 

结合dojo.provide一起来使用,非常强大。

YUI

下面的代码是YUI原始的实现方式:

  1. YAHOO.store.basket = function () {  
  2.  
  3.     //"private" variables:  
  4.     var myPrivateVar = "I can be accessed only within YAHOO.store.basket .";  
  5.  
  6.     //"private" method:  
  7.     var myPrivateMethod = function () {  
  8.         YAHOO.log("I can be accessed only from within YAHOO.store.basket");  
  9.     }  
  10.  
  11.     return {  
  12.         myPublicProperty: "I'm a public property.",  
  13.         myPublicMethod: function () {  
  14.             YAHOO.log("I'm a public method.");  
  15.  
  16.             //Within basket, I can access "private" vars and methods:  
  17.             YAHOO.log(myPrivateVar);  
  18.             YAHOO.log(myPrivateMethod());  
  19.  
  20.             //The native scope of myPublicMethod is store so we can  
  21.             //access public members using "this":  
  22.             YAHOO.log(this.myPublicProperty);  
  23.         }  
  24.     };  
  25.  
  26. } (); 

jQuery

jQuery里有很多Module模式的实现,我们来看一个不同的例子,一个library函数声明了一个新的library,然后创建该library的时候,在document.ready里自动执行init方法。

  1. function library(module) {  
  2. $(function() {  
  3. if (module.init) {  
  4. module.init();  
  5. }  
  6. });  
  7. return module;  
  8. }  
  9.    
  10. var myLibrary = library(function() {  
  11. return {  
  12. init: function() {  
  13. /*implementation*/ 
  14. }  
  15. };  
  16. }()); 

精彩图集

赞助商链接