設計模式提供了一些可重用的解決方案,這些方案適用於便攜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) })();