《Javascript 设计模式》-读书笔记
2014-08-16 22:05 臭小子1983 阅读(191) 评论(0) 编辑 收藏 举报第一章 设计模式类别
什么是设计模式:模式是一种可复用的解决方案。
一、设计模式有三种类别
1、创建型模式:专注于处理对象机制。包括:构造器、工厂、抽象、原型、单例、生成器
2、结构型模式:用于找出在不同对象之间建立关系密切的简单方法。 包括:装饰者、外观、享元、适配器、代理
3、行为模式:用于改善或简化系统中不同对象之间的通信。包括:迭代器、中介者、观察者、访问者
第二章 JavaScript设计模式
一、四种方法可以将健值赋给一个对象
1 <script> 2 // 1、使用点 3 var newObject = {}; 4 newObject.sonKey = "Hello World"; // 设置 5 var key = newObject.sonKey; // 获取 6 7 // 2、中括号语法 8 newObject['sonKey'] = "Hello World"; 9 var key = newObject['sonKey']; 10 11 // 3、object.defineProperty 12 </script>
1、创建对象两种常用方法
var newObject = {};
// 构造器的简洁记法
var newObject = new Object()
2、四种方法将键值赋值给一个对象
a、"点"语法 设置:newObject.someKey = "Hello World"; 获取:var key = newObject.someKey
b、中括号语法 设置:newObject["someKey"] = "Hello World"; 获取:var key = newObject["someKey"];
c、ECMAScript5中的defineProperty
d、defineProperties
模式一:Constructor(构造器)模式也可以叫构造函数
Constructor是一种在内存已分配权给该对象的情况下,用于初始化新创建对象的特殊方法
优点:每个实例都进行new实例化在内存中会简单创建一个空间,数据不会冲突
缺点:这种简单的构造函数中的write()方法都是公用,而不象是属性需要分离,而创建一个实例也会创建一个write()方法对性能上有所影响,建议使用porotype
1 <script> 2 3 // 创建对象 4 function Car(model, year, miles){ 5 this.model = model; 6 this.year = year; 7 this.miles = miles; 8 9 this.write = function(){ 10 return this.model + " has done " + this.year; 11 } 12 } 13 14 // 创建实例 15 var civic = new Car("Honda Civic", 2009, 3000); 16 var mondeo = new Car("Honda Civic", 2009, 3000); 17 18 civic.write(); 19 mondeo.write(); 20 </script>
带原型的构造函数
JS中的prototype属性,在调用构造函数创建对象后,新对象都会具有构造函数的所有属性
1 <script> 2 3 // 创建对象 4 function Car(model, year, miles){ 5 this.model = model; 6 this.year = year; 7 this.miles = miles; 8 } 9 10 Car.prototype = { 11 constructor: Car, 12 write: function(){ 13 return this.model + " has done " + this.year; 14 } 15 } 16 17 // 创建实例 18 var civic = new Car("Honda Civic", 2009, 3000); 19 var mondeo = new Car("Honda Civic", 2009, 3000); 20 21 civic.write(); 22 mondeo.write(); 23 </script>
模式二:Module(模块)模式
有几种用于实现模块的方法?
1、对象字面量
2、Module模式
3、AMD模块
4、CommonJS模块
5、ECMAScript Harmony模块
1、对象字面量
优点:有自己命名空间可以通过"."来访问全名空间
缺点:一个页面中如果有两个功能同时调用并且同时改变其属性会出现问题
1 <script> 2 var myModule = { 3 myProperty : "someValue", 4 5 myConifg: { 6 useCaching: true, 7 language: "en" 8 }, 9 10 // 方法 11 myMethod: function(){ 12 console.log("where in the world is paul irish today?"); 13 } 14 } 15 </script>
2、Module模式
模块模式(立即调用函数IIFE):可以定义私有和公有封装的方法,自动执行匿名函数,并返回暴露的公用接口
缺点:接口返回的count和money只是第一次调用的值,如果setData改变了count和money的值,这时候在调用countSsq.count不是为0,解决的方法就是通过getData来重新获取一下count和money的值
1 <script> 2 var countSsq = (function(){ 3 var count = 0; 4 var money = 0; 5 var setData = function(countNum, moneyNum){ 6 count = countNum; 7 money = moneyNum; 8 } 9 var getData = function(){ 10 return {count: count, money: money} 11 } 12 13 return { 14 count: count, 15 money: money, 16 setData: setData, 17 getData: getData 18 } 19 })(); 20 </script>
揭示模块模式:
1 <script> 2 var myModule = (function(){ 3 4 var privateVar = "Ben Cherry", publicVar = "Hey tthere"; 5 6 function privateFunction(){ 7 console.log("name:" + privateVar); 8 } 9 10 function publicFunction(strName){ 11 privateVar = strName; 12 } 13 14 function publicGetName(){ 15 privateFunction() 16 } 17 18 // 将暴露的公有指针指向到私有的函数和属性上 19 return { 20 setName: publicFunction, 21 greeting: publicVar, 22 getNam: publicGetName 23 } 24 })(); 25 </script>
引入混入
比如我们引用了如jquery的库,可以将jquery对象通过匿名函数传递进来,并按我们自己希望的取个本地的中
1 <script> 2 var myModule = (function(JQ){ 3 4 // JQ为jQuery对象通过参数传递进来,将在模块内转成自己所定义的名子 5 function privateMethod(){ 6 JQ(".box").html("test"); 7 } 8 9 return { 10 publicMethod: function(){ 11 privateMethod(); 12 } 13 } 14 15 })(jQuery) 16 </script>
引出
1 <script> 2 var myModule = (function(){ 3 4 // 模块对象 5 var module = {}, 6 privateVariable = "hello world"; 7 8 module.publicProperty = "Foobar"; 9 module.publicMethod = function(){ 10 console.log(privateVariable); 11 } 12 13 return module; // 将模块对象暴露给外部 14 })() 15 16 myModule.publicMethod(); 17 </script>
模式三、单例模式(Singleton)
单例模式限制了类的实例化次数只能一次
1 <script> 2 var mySingleton = (function () { 3 4 /* 这里声明私有变量和方法 */ 5 var privateVariable = 'something private'; 6 function showPrivate() { 7 console.log(privateVariable); 8 } 9 10 /* 公有变量和方法(可以访问私有变量和方法) */ 11 return { 12 publicMethod: function () { 13 showPrivate(); 14 }, 15 publicVar: 'the public can see this!' 16 }; 17 })(); 18 19 mySingleton.publicMethod(); // 输出 'something private' 20 console.log(mySingleton.publicVar); // 输出 'the public can see this!' 21 </script>
模式四、观察者模式
目标:维护一系列观察者,方便添加或删除观察者
观察者:目标状态发生改变时需获得通知的对象提供一个更新接口
具体目标:状态发生改变时向观察者发出通知,存储具体观察者
具体观察者:存储一个指向具体目标的引用,实现观察者更新接口,以自身状态与目标的状态保持一致
1 <script> 2 3 // 观察者 4 function Observer(){ 5 this.observerList = []; 6 } 7 8 Observer.prototype = { 9 constructor: Observer, 10 11 // 向数据中添加数据 12 add: function(obj){ 13 return this.observerList.push(obj); 14 }, 15 16 // 清空数据 17 empty: function(){ 18 this.observerList = []; 19 }, 20 21 // 获取对象的长度 22 count: function(){ 23 return this.observerList.length; 24 } 25 } 26 27 28 // 扩展对象的方法 29 function extend(obj, extension){ 30 for(var key in obj){ 31 extension[key] = obj[key]; 32 } 33 } 34 35 // 模拟目标 36 function Subject() { 37 this.observerList = new Observer(); // 将观察者引入到目标的属性 38 } 39 40 Subject.prototype = { 41 constructor: Subject, 42 43 addObserver: function(data){ 44 this.observerList.add(data); 45 }, 46 47 getCount: function(){ 48 return this.observerList.count(); 49 } 50 } 51 52 var oSub = new Subject(); 53 oSub.addObserver("aaa"); 54 console.log(oSub.getCount()); 55 56 oSub.addObserver("bbb"); 57 oSub.addObserver("ccc"); 58 console.log(oSub.getCount()); 59 </script>
模式五、中介者模式
中介者模式的功能就是封装了多个类之间的交互
http://ju.outofmemory.cn/entry/107912
Why Mediator ?
各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉及到修改很多其他对象的行为,如果使用Mediator模式,可以使各个对象间的耦合松散,只需关心和 Mediator的关系,使多对多的关系变成了一对多的关系,可以降低系统的复杂性,提高可修改扩展性。
使用中介者模式的场合
1.一组定义良好的对象,现在要进行复杂的通信。
2.定制一个分布在多个类中的行为,而又不想生成太多的子类。
可以看出,中介对象主要是用来封装行为的,行为的参与者就是那些对象,但是通过中介者,这些对象不用相互知道。(迪米特法则的具体实现)
使用中介者模式的优点:
1.降低了系统对象之间的耦合性,使得对象易于独立的被复用。
2.提高系统的灵活性,使得系统易于扩展和维护。
使用中介者模式的缺点:
中介者模式的缺点是显而易见的,因为这个“中介“承担了较多的责任,所以一旦这个中介对象出现了问题,那么整个系统就会受到重大的影响。
1 <script> 2 3 // 中介者模式的简单实现,暴露publih()和subscribe() 4 var mdeiator = (function(){ 5 6 // 存储可被广播或监听的topic 7 var topics = {}; 8 9 // 订阅一个topic,提供一个回调函数,一旦topic被广告就执行回调 10 var subscribe = function(ic, fn){ 11 12 // 如果存储中没有当前数据则创建一个 13 if(!topics[ic]){ 14 topics[ic] = []; 15 } 16 17 topics[ic].push({context: this, callback: fn}); 18 return this; 19 } 20 21 // 发布/广播事件到程序的剩余部分 22 var publish = function(ic){ 23 var args; 24 25 if(!topics[ic]){ 26 return false; 27 } 28 29 args = Array.prototype.slice.call(arguments, 1); 30 31 for(var i= 0,l = topics[ic].length; i<l; i++){ 32 var subscription = topics[ic][i]; 33 subscription.callback.applay(subscription.context, args); 34 } 35 36 return this; 37 } 38 39 return { 40 publish: publish, 41 subscribe: subscribe, 42 installTo: function(obj){ 43 obj.subscribe = subscribe; 44 obj.publish = publish; 45 } 46 } 47 })(); 48 49 mdeiator.subscribe("aa", function (){ alert("haha"); }); 50 mdeiator.subscribe("aa", function (){ alert("haha"); }); 51 52 mdeiator.publish("aa"); 53 54 </script>
第十一章 模块化的JavaScript设计模式
一、脚本加载器
AMD、CommandJS和seajs三种模块化开发
1、AMD:异步模块定义的整体目标是提供模块化的.
模块入门:
模块定义define方法和用于处理依赖加载的require方法
第10章 JavaScript MV*设计模式
一、三个架构模式
1、MVC:模型、视图、控制器
2、MVP:模型、视图、表示器
3、MVVM:模型、视图、视图模型
二、MVC
MVC它将业务数据(modle)、用户界面(view)隔离、第三个组件(controller)管理逻辑和用户输入.
当UI的变化引起模型属性改变时,模型会触发"change"事件; 所有显示模型数据的视图会接收到该事件的通知,继而视图重新渲染。 你无需查找DOM来搜索指定id的元素去手动更新HTML。 — 当模型改变了,视图便会自动变化
1、Modle模型
管理应用于程序的数据,不涉及用户界面,也不涉及表示层
1 <script> 2 var Photo = Backbone.model.extend({ 3 4 // photo默认属性 5 defaults : { 6 src: "place.jpg", 7 caption: "a default image", 8 viewed: false 9 }, 10 11 // 确保每一个photo都有一个src 12 init: function (){ 13 this.set({ "src": this.defaults.src }); 14 } 15 }) 16 </script>
Model主要是与业务数据有关
2、View(视图)
视图是Model(模型)的可视化表示,用户可以与视图进行交互,包括读取和编辑模型,在模型中获取或设置障碍属性值
模板:
在支持MVC/MV*的框架中,javascript模版与view的关系
javascript模板通常是用于将view模板定义为包含模板变量的标记录
1 Handlebars.js 2 <li> 3 <h2>{{caption}}</h2> 4 <img class="source" src="{{src}}"> 5 <div> 6 {{metadata}} 7 </div> 8 </li>
3、Controller(控制器)
控制器是模型和视图之间的中介,当用户操作视图时,控制器负责更新模型
BackBone中文官网:http://www.csser.com/tools/backbone/backbone.js.html
第七章 设计模式类别