构建大型程序最大的秘密
这次我们提议的架构使用了我们都很熟知的设计模式:module, facade和mediator。
Module模式 1、module模式是一个比较流行的设计模式,它可以通过大括号封装私有的变量、方法、状态等,通过包装这些内容,一般全局的对象不能直接访问,在这个设计模式里,只返回一个API,其它的内容全部被封装成私有; 2、这个模式和自执行的函数表达式比较相似,唯一不同的是module模式返回的是对象,而自执行函数返回的是function; 3、javascript没有声明private、public修饰符,我们可以通过return语句返回我们要公共的方法,达到public效果,而其它的为private; 示例:统计对象 需求:一个超市有多种产品,现在要求统计多种产品的价格 思想:把超市里的每一种产品作为一个对象,产品有名称、价格,如:{item:'桔子',price:0.5} --> <script type="text/javascript"> var md = (function() { //return的对象直接赋值给了md var ar = []; //private return { //public add: function(values) { ar.push(values); }, count: function() { //有多少个对象 return ar.length; }, total: function(){ //统计价格 var q = this.count(),p=0;//this为md对象的构造函数,this.constructor == md.constructor while(q--){ p+= ar[q].price; } return p; } } }()); //把对象添加到数组里 md.add({item:'桔子',price:0.5}); md.add({item:'苹果',price:2.0}); alert("种类:" + md.count()); //种类:2 alert("总价:" + md.total()); //总价:2.5 </script>
<!-- Module模式,工厂风格 标题:一个library函数声明了一个新的library对象 --> <script type="text/javascript"> function library(module) { (function() { if (module.init) { module.init(); //init()已被执行 } })(); return module; } var lib = library(function() { return { init: function() { alert('init'); }, msg:function(s){ return s; } }; }()); alert(lib.msg('msg')); //调用执行,结果:msg
<!-- Facade模式 定义:Facade(外观)模式为子系统中的各类(或结构与方法)提供一个简明一致的界面,隐藏子系统的复杂性,使子系统更加容易使用。 遇到以下情况使用Facade模式: 1、当你要为一个复杂子系统提供一个简单接口时。 2、客户程序与抽象类的实现部分之间存在着很大的依赖性。 3、当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,你可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。 实例:下面这个例子了,可以看到我们提供了很多私有的方法,然后通过暴露一个简单的 API来让外界执行调用内部的方法 --> <script type="text/javascript"> var module = (function () { var _private = { i: 5, get: function () { alert('current value:' + this.i); }, set: function (val) { this.i = val; }, run: function () { alert('running'); }, jump: function () { alert('jumping'); } }; return { facade: function (args) { _private.set(args.val); _private.get(); if (args.run) { _private.run(); } } } } ()); module.facade({run:true, val:10});//结果:outputs current value: 10, running </script>
<!-- Mediator模式 定义:Mediator(中介者)模式为用一个中介对象来封装一系列关于对象交互行为。 遇到以下情况使用Mediator模式: 各个对象之间的交互操作非常多;每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉及到修改很多其他对象的行为,如果使用Mediator模式,可以使各个对象间的耦合松散,只需关心和 Mediator的关系,使多对多的关系变成了一对多的关系,可以降低系统的复杂性,提高可修改扩展性. --> <script type="text/javascript"> var mediator = (function(){ //定义mediator接口,用来定义成员对象之间的交互联系方式: var subscribe = function(channel, fn){ //订阅行为 if (!mediator.channels[channel]) mediator.channels[channel] = []; mediator.channels[channel].push({ context: this, callback: fn }); return this; }, publish = function(channel){ //公布行为 if (!mediator.channels[channel]) return false; var args = Array.prototype.slice.call(arguments, 1); for (var i = 0, l = mediator.channels[channel].length; i < l; i++) { var subscription = mediator.channels[channel][i]; subscription.callback.apply(subscription.context, args); } return this; }; return { //返回对象 channels: {}, publish: publish, subscribe: subscribe, installTo: function(obj){ //安装行为 obj.subscribe = subscribe; obj.publish = publish; } }; }()); //1、向中介者订阅行为 mediator.name = "tim"; mediator.subscribe('nameChange', function(arg){ console.log(this.name); this.name = arg; console.log(this.name); }); //2、让中介者发布行为 mediator.publish('nameChange', 'david'); //tim, david //3、安装行为 var obj = { name: 'sam' }; mediator.installTo(obj); obj.subscribe('nameChange', function(arg){ console.log(this.name); this.name = arg; alert(this.name); }); obj.publish('nameChange', 'john'); //sam, john </script>
总结:
1、mediator只有在facade授权检测以后才能进行信息处理。
2、各个模块之间联系的越密切,重用性越小,改变起来困难越大。
3、构建大型程序最大的秘密就是从来不构建大型程序,而是将程序分解成各个小的模块去做,让每个小模块都可测试,可size化,然后集成到程序里。
4、一切皆可变,所以要抽象。
"唯有高屋建瓴,方可水到渠成"