设计模式提供了一些可重用的解决方案,这些方案适用于便携javaScript Web应用.
参考学习 Deven dalao 的文章做为学习笔记.
原文地址
参考文章javascript
这种特殊的方法,被用于内存在内存初始化以后分配一个新建立的对象,javaScript是面相对象的,因此咱们研究最多的就是 对象构造器(object Constructor)java
// 这里有3中方式去建立一个 javaScript对象 var newObject_0 = {}; // OR var newObject_1 = Object.create(Object.prototype); // OR var newObject_2 = new Object();
// 有如下几种方式能够将属性放入一个对象 // 1. . // 设置属性 newObject_0.hello = "hello newObject_0"; // 2.方括号 newObject_0['square_hello'] = "hello newObject_0"; // 3.Object.defineProperty 兼容性参考 http://kangax.github.io/compat-table/es5/ Object.defineProperty(newObject_1, "someKey", { value: "for more control of the property's behavior", writable: true, enumerable: true, configurable: true }); // 咱们能够写个方法 const defindProp = (obj, key, value) => { var config = { value: value, writable: true, enumerable: true, configurable: true }; Object.defineProperty(obj, key, config) } const myObj = Object.create(Object.prototype); defindProp(myObj, 'eat', '什么都吃'); defindProp(myObj, 'money', '0'); // 4. Object.defineProperties Object.defineProperties(newObject_2, { "key1": { value: "Hello World", writable: true }, "key2": { value: "Foo bar", writable: false } }); console.log(newObject_2); // 若是须要访问函数的属性,你须要去初始化对象 // const object = new constructorObject(); // 据此 new 关键词在这里告诉javaScript constructorObject 应当充当一个构造器,另外这个方法并不支持继承 // 基础构造器 function Computer(cpu, os) { this.cpu = cpu; this.os = os; this.toString = () => this.cpu + '系统是:' + this.os } const WinPc = new Computer('i7', 'windows'); const LinuxPc = new Computer('i5', 'Linux'); console.log({ WinPc: WinPc.toString(), LinuxPc: LinuxPc.toString() })
原型模式主要基于原型继承,被建立的对象充当其余对象的原型,实际上原型 (prototypes act)做为每一个对象构造器的蓝图git
var myCar = { name: "Ford Escort", drive: function () { console.log("Weeee. I'm driving!"); }, panic: function () { console.log("Wait. How do you stop this thing?"); } }; // Use Object.create to instantiate a new car var yourCar = Object.create(myCar); // Now we can see that one is a prototype of the other console.log(yourCar.name);
在模块(Module)设计模式下,对原型(Prototype)模式进行了一些改进,没模块模式使用两种不一样的修饰符(private 和 public),你能够建立互不冲突的类似函数属性,你能够灵活的重命名共有函数(functions publicly)。这个模式的缺陷是不能 覆盖(override )外部环境中建立的函数github
var myModule = { myProperty: "someValue", // object literals can contain properties and methods. // e.g we can define a further object for module configuration: myConfig: { useCaching: true, language: "cn" }, // 说点什么 saySomething: function () { console.log("吃了么?"); }, // 输出当前状态 reportMyConfig: function () { console.log("Caching is: " + (this.myConfig.useCaching ? "enabled" : "disabled")); }, // override the current configuration updateMyConfig: function (newConfig) { if (typeof newConfig === "object") { this.myConfig = newConfig; console.log(this.myConfig.language); } } }; myModule.saySomething(); myModule.reportMyConfig(); myModule.updateMyConfig({ language: "en", useCaching: false }); myModule.reportMyConfig();
在仅须要建立一个实例的状况下(如一个数据库链接),这个模式就是必须的。在这个模式种,只有在关闭链接或者肯定打开新实例钱必须关闭已有实例时能够建立一个新实例。这个模式也成为严格模式(strict pattern),他的一个缺陷是在测试时的体验糟糕,由于他很难单独拿出来进行测试数据库
function DatabaseConnection() { let databaseInstance = null; // tracks the number of instances created at a certain time let count = 0; function init() { console.log(`Opening database #${count + 1}`); //now perform operation } function createIntance() { if (databaseInstance == null) { databaseInstance = init(); } return databaseInstance; } function closeIntance() { console.log('closing database'); databaseInstance = null; } return { open: createIntance, close: closeIntance } } const database = DatabaseConnection(); database.open(); //Open database #1 database.open(); //Open database #1 database.open(); //Open database #1 database.close(); //close database
工厂模式的创新之处在于他不须要 构造器(constructor)就能建立对象.他提供了一个通用接口去建立兑现,你能够指定想要的工厂对象(actory objects)类型。这样一来,咱们只须要指定对象而后 工厂实例化并返回对象给咱们使用。当对象组件设置起来很复杂,并但愿根据不一样的环境建立不一样的对象实例时候,建议使用工厂模式。在处理多共享相同属性的小型对象,以及建立一些须要解耦(decoupling)的组合对象的时候,也可使用工厂模式segmentfault
// Dealer A DealerA = {}; DealerA.title = function title() { return "Dealer A"; }; DealerA.pay = function pay(amount) { console.log( `set up configuration using username: ${this.username} and password: ${ this.password }` ); return `Payment for service ${amount} is successful using ${this.title()}`; }; //Dealer B DealerB = {}; DealerB.title = function title() { return "Dealer B"; }; DealerB.pay = function pay(amount) { console.log( `set up configuration using username: ${this.username} and password: ${this.password}` ); return `Payment for service ${amount} is successful using ${this.title()}`; }; //@param {*} dealerOption //@param {*} config function DealerFactory(dealerOption, config = {}) { const dealer = Object.create(dealerOption); Object.assign(dealer, config); return dealer; } const dealerFactory = DealerFactory(DealerA, { username: "user", password: "pass" }); console.log(dealerFactory.title()); console.log(dealerFactory.pay(12)); const dealerFactory2 = DealerFactory(DealerB, { username: "user2", password: "pass2" }); console.log(dealerFactory2.title()); console.log(dealerFactory2.pay(50));
观察者(Observer)模式在多对象同时(simultaneously)与其余对象通讯(communicate )的场景中使用很方便。在观察者模式下,没有非必须的push 和pull ,相比之下,所涉及的模块仅会修改数据的当前状态windows
function Observer() { this.observerContainer = []; } Observer.prototype.subscribe = function (element) { this.observerContainer.push(element); } // the following removes an element from the container Observer.prototype.unsubscribe = function (element) { const elementIndex = this.observerContainer.indexOf(element); if (elementIndex > -1) { this.observerContainer.splice(elementIndex, 1); } } /** * we notify elements added to the container by calling * each subscribed components added to our container */ Observer.prototype.notifyAll = function (element) { this.observerContainer.forEach(function (observerElement) { observerElement(element); }); };
命令(Command)模式讲方法的调用,操做和请求封装到单个对象中,一边能够自行传递方法调用。命令模式能够从任何正在执行的命令中发出命令,并将责任委托给以前不一样的对象,这些命令以run() 和 execute() 格式显示设计模式
(function () { var carManager = { //information requested requestInfo: function (model, id) { return "The information for " + model + " with ID " + id + " is foo bar"; }, // now purchase the car buyVehicle: function (model, id) { return "You have successfully purchased Item " + id + ", a " + model; }, // now arrange a viewing arrangeViewing: function (model, id) { return "You have successfully booked a viewing of " + model + " ( " + id + " ) "; } }; carManager.execute = function (name) { return carManager[name] && carManager[name].apply(carManager, [].slice.call(arguments, 1)); }; let carExec = carManager.execute("buyVehicle", "Ford Escort", "453543"); // console.log(carExec) })();