单体模式:保证一个特定类仅有一个实例;即第二次使用同一个类创建新对象时,应该得到与第一个所创建对象完全相同对象;
- 在JS中,可以认为每次在使用对象字面量创建对象的时候,实际上就在创建一个单体;
- 当使用new创建新对象时
- 使用静态属性中的实例:
function Universe() { if(typeof Universe.instance === 'object') { return Universe.instance; } this.start_time = 0; this.bang = 'Big'; Universe.instance = this; return this; }
- 采用闭包包含单个实例:
function Universe1() { var instance = this; this.start_time = 0; this.bang = 'Big'; Universe1 = function() { return instance; } }
var Universe; (function () { var instance; Universe = function Universe() { if(instance) { return instance; } instance = this; //增加功能 this.start_time = 0; this.bang = 'Big'; } })();
- 使用静态属性中的实例:
工厂模式:
根据字符串指定地类型在运行时创建对象地方法
工厂模式地目的使为了创建对象
- 当创建对象时执行重复操作
- 再编译时不知道具体类型地情况下,为工厂客户提供一个创建对象的接口
function CarMaker() {}; CarMaker.prototype.drive = function() { return "Vroom, I have " + this.doors + " doors"; }; CarMaker.factory = function(type) { var constr = type, newcar; //如果构造函数不存在,则抛出错误 if(typeof CarMaker[constr] != "function") { throw { name: "Error", message: constr + " doesn't exist" }; } //构造函数是已知存在的;使原型继承父类,但仅继承一次 if(typeof CarMaker[constr].prototype.drive !== 'function') { CarMaker[constr].prototype = new CarMaker(); } //创建一个新的实例 newcar = new CarMaker[constr](); //选择性地调用一些方法,然后返回 return newcar; }; CarMaker.Compact = function() { this.doors = 4; }; CarMaker.Convertible = function() { this.doors = 2; } CarMaker.SUV = function() { this.doors = 24; } var corolla = CarMaker.factory('Compact'); var solstice = CarMaker.factory('Convertible'); var cherokee = CarMaker.factory('SUV'); corolla.drive(); solstice.drive(); cherokee.drive();
内置对象工厂:对于自然工厂的例子,可以考虑内置的Object()构造函数;它也根据输入类型而创建不同的对象;
迭代器模式:
提供一个API来遍历或操纵复杂地自定义数据结构
迭代访问一个包含某些数据集合的对象的模式;
var agg = (function() { var index = 0, data = [1,2,3,4,5], length = data.length; return { next: function() { var element; if(!this.hasNext()) { return null; } element = data[index]; index = index + 2; return element; }, hasNext: function() { return index < length; }, //重置指针到初始化位置 rewind: function() { index = 0; }, //返回当前元素 current: function() { return data[index]; } } }()); //测试 while(agg.hasNext()) { console.log(agg.next()); } agg.rewind(); console.log(agg.current());
装饰者模式
可以再运行时动态添加附加功能到对象中;比较方便的特征时其预期行为可制定和可配置;
function Sale(price) { this.price = price || 100; } Sale.prototype.getPrice = function() { return this.price; } Sale.decorators = {}; //增加联邦税 Sale.decorators.fedtax = { getPrice: function() { var price = this.uber.getPrice(); price += price * 5/ 100; return price; } }; //增加省级税 Sale.decorators.quebec = { getPrice: function() { var price = this.uber.getPrice(); price += price * 7.5 /100; return price; } }; //转化为美元 Sale.decorators.money = { getPrice: function() { return "$" + this.uber.getPrice().toFixed(2); } }; //格式化为CDN Sale.decorators.cdn = { getPrice: function() { return "CDN$ " + this.uber.getPrice().toFixed(2); } }; Sale.prototype.decorate = function(decorator) { var F = function() {}, overrides = this.constructor.decorators[decorator], i, newobj; F.prototype = this; newobj = new F(); newobj.uber = F.prototype; for(i in overrides) { if(overrides.hasOwnProperty(i)) { newobj[i] = overrides[i]; } } return newobj; } var sale = new Sale(100); sale = sale.decorate('fedtax'); sale = sale.decorate('quebec'); sale = sale.decorate('money'); sale.getPrice(); var newsale = new Sale(200); newsale = newsale.decorate('cdn'); newsale.getPrice();
使用列表实现
function Sale(price) { this.price = price; this.decorators_list = []; } Sale.decorators = {}; Sale.decorators.fedtax = { getPrice: function(price) { return price + price * 5 / 100; } }; Sale.decorators.quebec = { getPrice: function(price) { return price + price * 7.5 /100; } }; Sale.decorators.money = { getPrice: function(price) { return "$" + price.toFixed(2); } }; Sale.prototype.decorate = function(decorator) { this.decorators_list.push(decorator) }; Sale.prototype.getPrice = function() { var price = this.price, i, max = this.decorators_list.length, name; for(i = 0; i < max; i++) { name = this.decorators_list[i]; price = Sale.decorators[name].getPrice(price); } return price; } var sale = new Sale(100); sale.decorate('fedtax'); sale.decorate('quebec'); sale.decorate('money'); console.log(sale.getPrice());