JavaScript设计模式 -- 读书笔记
JavaScript设计模式
一、 设计模式
一个模式就是一个可重用的方案;
有效的解决方法、易重用、善于表达该解决方案;
未通过“模式特性”测试的模式称为模式原型;
三规则:适用性、有用性、可用性;
三个分类:
创建型设计模式
构造器模式(Constructor)、工厂模式(Factory)、抽象工厂模式(Abstract)、
原型模式(Prototype)、单例模式(Singleton)、建造者模式(Builder)
结构设计模式
装饰模式、外观模式、适配器模式、代理模式
行为设计模式
迭代模式、中介者模式、观察者模式、访问者模式
二、 JavaScript设计模式
构造器模式
function Car(model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
}
Car.prototype.toString = function() {
return this.model + “ has done ” + this.miles + “ miles”;
}
var sampleCar = new Car(“Honda”, 2009, 20000);
模块化模式
在一个单一对象中包含共有/私有的方法和变量,全局范围中屏蔽特定部分,减少与其他脚本区域定义的函数名称冲突。
私有信息:闭包实现 → 函数域模拟公有和私有概念
var myNamespace = (function() {
var counter = 0;
return {
increamentCounter: function() {
return counter++;
},
resetCounter: function () {
counter = 0;
}
}
} ) ();
myNamespace.incrementCounter();
myNamespace.resetCounter();
缺点:当想要改变某些成员可见性时,需要在所有使用该成员地方修改代码
暴露式模块模式
var myRevealingModule = function() {
var privateCounter = 0;
function privateFunction() {
privateCounter++;
}
function publicFunction() {
publicIncrement();
}
function publicIncrement() {
privateFunction();
}
function publicGetCount() {
return privateCounter;
}
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetcount
};
} ();
myRevealingModule.start();
单例模式
一个类只有一个实例化对象;
实现方式:创建一个类,这个类包含一个方法。在没有对象存在时,该方法创建一个新的实例对象;对象存在时,返回该对象的引用;
每个类只有一个实例,该实例必须通过一个接口,才允许访问;
子类如果要扩展这个唯一实例,可不用修改代码就能使用扩展后的实例;
var mySingleton = (function() {
var instance;
function init() {
function privateMethod() {
console.log(“ I am private”);
}
var privateVariable = “I am also private”;
var privateRandomNumber = Math.random();
return {
publicMethod: function() {
console.log(“ The public can see me !”);
},
publicProperty: “I am also public”,
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
getInstance: function() {
if( ! instance) {
instance = init();
}
return instance;
}
};
}) ();
观察者模式
被观察者:提供用于增加和删除观察者的方法
观察者:提供一个接口,当被观察者状态变化时,得到通知
被观察者:
fuction ObserverList() {
this.observerList = [];
}
ObserverList.prototype.Add = function(obj) {
return this.observerList.push(obj);
}
ObserverList.prototype.Empty = function() {
this.observerList = [];
}
ObserverList.prototype.Count = function() {
return this.observerList.length;
}
ObserverList.prototype.Get = function(index) {
if( index > -1 && index < this.observerList.length) {
return this.observerList[index];
}
}
ObserverList.prototype.Insert = function(obj, index) {
var pointer = -1;
if(index === 0) {
this.observerList.unshift(obj);
pointer = index;
} else if(index === this.observerList.length) {
this.observerList.push(obj);
pointer = index;
}
return pointer;
}
ObserverList.prototype.IndexOf = function(obj, startIndex) {
var i = startIndex,
pointer = -1 ;
while(i < this.observerList.length) {
if(obj == observerList[i]) {
pointer = i;
break;
}
i++
}
return pointer;
}
ObserverList.prototype.RemoveAt = function(index) {
if(index ===0) {
this.observeList.shift();
} else if( index === this.observerList.length - 1) {
this.observerList.pop();
}
}
function extend(extension, obj) {
for(var key in extension) {
obj[key] = extension[key];
}
}
观察者:
function Subject() {
this.observes = new ObserverList();
}
Subject.prototype.AddObserver = fuction(observer) {
this.observers.Add(observer);
}
Subject.prototype.RemoveObserver = function(observer) {
this.observers.RemoveAt(this.observers.IndexOf(observer,0));
}
Subject.prototype.Notify = function(context) {
var observerCount = this.observers.Count();
for(var i = 0; i < observerCount; i++) {
this.observers.Get(i).Update(context);
}
}
function Observer() {
this.Update = function() {
……
};
}
中介者模式
……
原型模式
ver vehicle = {
getModel: function() {
console.log(“ The model of this vehicle is ..” + this.model);
}
};
ver car = Object.create(vehicle, {
“id”: {
value: MY_GLOBAL.nextId(),
enumerable: true
},
“model”: {
value: “Ford”,
enumerable: true
}
});
-------------------------------------------------------------------------------------------
var verclePrototype = {
init: function(carModel) {
this.model = carModel;
},
getModel: function() {
console.log(“ The model of this vehicle is ..” + this.model);
}
};
function vehicle(model) {
function F() {};
F.prototype = verclePrototype;
var f = new F();
f.init(model);
return f;
}
命令模式
将方法的调用,请求或者操作封装到一个单独对象中。
var CarManager = {
requestInfo: function(model, id) {
return “ The information for ” + model + “ with ID ” + id + “ is foobar”;
},
buyVehicle: function(model, id) {
…
},
arrangeViewing: function(model, id) {
…
}
};
CarManager.execute = function(name) {
return CarManager[name] && CarManager[name].apply( CarManager,
[].slice.call(arguments, 1)
);
};
CarManager.execute( "arrangeViewing", "Ferrari", "14523" );
CarManager.execute( "requestInfo", "Ford Mondeo", "54323" );
CarManager.execute( "requestInfo", "Ford Escort", "34232" );
CarManager.execute( "buyVehicle", "Ford Escort", "34232" );
外观模式
jQuery的$(document).ready(..),内部方法驱动bindReady()
bindReady: function() {
if(document.addEventListener) {
document.addEventLister(“DOMContentLoaded”,
DOMContentLoaded, false);
window.addEventListener(“load”, jQuery.ready, false);
} else if(document.attachEvent) {
document.attachEvent(“onreadystatechange”, DOMContentLoaded);
window.attachEvent(“onload”, jQuery.ready);
}
}
工厂模式
function Car(options) {
this.doors = options.doors|| 4;
this.state = options.state || “brand new”;
this.color = options.color || “silver”;
}
function Truck(options) {
this.state = options.state || “used”;
this.wheelSize = options.wheelSize || “large”;
this.color = options.color || “blue”;
}
function VehicleFactory() {
VehicleFactory.prototype.vehicleClass = Car;
VehicleFactory.prototype.createVehicle = function(options) {
if(options.vehicleType == “car”) {
this.vehicleClass = Car;
} else {
this.vehicleClass = Truck;
}
return new this.vehicleClass(options);
}
};
var carFactory = new VehicleFactory();
var car = carFactory.createVehicle({
vehicleType: “car”,
color: “yellow”,
doors: 6
});
应用场景:
l 当我们的对象或者组件设置涉及到高程度级别的复杂度时
l 当我们需要根据我们所在的环境方便的生成不同对象的实体时
l 当我们在许多共享同一个属性的许多小型对象或组件上工作时
l 当带有其它仅仅需要满足一种API约定的对象的组合对象工作时
Mixin模式
var Mixin = function() {};
Mixin.prototype = {
driveForward: function() {},
driveBackward: function() {},
driveSideways: function() {}
}
function augment(receivingClass, givingClass) {
if(argument[2]) {
for(var i =2, len= argument.length; i < len; i++) {
receivingClass.prototype[argument[i]]=givingClass.prototype[argument[i]];
}
} else {
for(var methodName in givingClass) {
if(!Object.hasOwnProperty(receivingClass.prototype, methodName)) {
receivingClass.prototype[methodName]= givingClass.prototype[methodName];
}
}
}
}
augment( Car, Mixin, "driveForward", "driveBackward" );
var myCar = new Car({
model: "Ford Escort",
color: "blue"
});
装饰模式
旨在提升重用性能的一种结构性设计模式;
典型的装饰器提供了向一个系统中现有的类动态添加行为的能力;
亨元模式
数据层:基于存储在内存中的大量相同对象的数据共享;
DOM层:享元模式作为事件管理中心,以避免将事件处理程序关联到我们需要相同行为父容器的所有子节点上。
三、 JavaScript MV*模式
- MVC模式
Models:一个业务应用的数据模型。
Views:视图是模型的可视化表现。
Controllers:控制器是模型和视图之间的中介。
当模型被改变时,它会通知观察者(视图)一些东西已经被更新了,这是MVC中最重要的关系。
- MVP模式
P:展示器
- MVVM模式
四、 模块化JavaScript设计模式
- AMD
异步模块定义(Asynchronous Module Definition)
异步方式加载模块,模块的加载不影响它后面语句的运行。
var math = require(‘math’);
math.add(2, 3);
浏览器端,因为模块都放在服务器端吗,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于假死状态。
因此,浏览器端的模块,不能采用同步加载,只能采用异步加载。
require([modele], callback);
require([‘math’], function(math) {
math.add(2, 3);
});
math.add()与math模块加载不是同步的;