開發人員都應該瞭解的 7 種 JavaScript 設計模式
通過設計模式,我們可以將許多開發人員的經驗結合起來,以優化過的方式來構造程式碼,從而解決我們所面對的問題。設計模式還提供了用於描述問題解決方案的通用詞彙表,而不是去枯燥地描述程式碼的語法和語義。
JavaScript 設計模式可幫助開發人員編寫出井井有條、美觀且結構合理的程式碼。儘管設計模式很容易重用,但它們並不是要取代開發人員的工作;它們是開發人員的支援與輔助,提供了與特定應用程式無關的通用解決方案,從而儘量避免那些可能導致 Web 應用程式的開發工作出現重大問題的小漏洞。
與臨時方案相比,它們消除了不必要的重複,從而縮減了程式碼庫的整體大小,並讓我們的程式碼更加健壯。
在本文中,我將探討 7 種最出色和最受歡迎的 JavaScript 設計模式,這些模式主要歸為以下三類:創作設計模式、結構設計模式和行為設計模式。
1、建構函式設計模式
這是一種特殊的方法,用於在分配記憶體後初始化新建立的物件。由於 JavaScript 一般來說是面向物件的,所以它打交道最多的就是物件。於是我打算深入研究物件建構函式。在 JavaScript 中建立新物件有三種方法可用。
以下建立建構函式設計模式的一種方法。
// 建立一個新的空物件 var newObject = {}; // 建立一個新的空物件 var newObject = Object.create(Object.prototype);var newObject = newObject();
要訪問函式的屬性,你需要初始化物件。
const object = new ConstructorObject();
上面的 new 關鍵字告訴 JavaScript,一個 constructorObject 應該充當一個建構函式。這個設計模式並不支援繼承。更多細節可以參考這裡。
2、原型模式
原型模式是基於原型繼承的。在這種模式中,被建立的物件充當其他物件的原型。實際上,原型(prototype)是被建立的每個物件建構函式的藍圖。
示例:
var myCar= { name:"Ford Escort", brake:function(){ console.log("Stop! I am applying brakes"); } Panic : function (){ console.log ( "wait. how do you stop thuis thing?") } } // 使用 object create 實個新的例化一 car var yourCar= object.create(myCar); // 現在它就是另一個的原型了 console.log (yourCar.name);]
3、模組設計模式
模組(module)設計模式對原型模式做了一些改進。模組模式設定了不同型別的修飾符(私有和公共)。你可以建立相似的函式或屬性而不會發生衝突。我們還可以靈活地公開重新命名函式。這個設計模式的一個缺陷是無法覆蓋(override)外部環境中建立的函式。
示例:
function AnimalContainter () { const container = []; function addAnimal (name) { container.push(name); } function getAllAnimals() { return container; } function removeAnimal(name) { const index = container.indexOf(name); if(index < 1) { throw new Error('Animal not found in container'); } container.splice(index, 1) } return { add: addAnimal, get: getAllAnimals, remove: removeAnimal } } const container = AnimalContainter(); container.add('Hen'); container.add('Goat'); container.add('Sheep'); console.log(container.get()) //Array(3) ["Hen", "Goat", "Sheep"] container.remove('Sheep') console.log(container.get()); //Array(2) ["Hen", "Goat"]
4、單例模式
在僅需要建立一個例項的情況下(例如一個數據庫連線),這個模式是必需的。在這個模式中,只能在關閉連線時建立一個例項,或者在開啟新例項之前必須關閉已有的例項。此模式也稱為嚴格模式,它的一個缺點是測試時的體驗很差,因為它隱藏的依賴項物件很難挑出來進行測試。
示例:
function DatabaseConnection () { let databaseInstance = null; // 追蹤特定時間建立例項的數量 let count = 0; function init() { console.log(`Opening database #${count + 1}`); // 現在執行操作 } function createIntance() { if(databaseInstance == null) { databaseInstance = init(); } return databaseInstance; } function closeIntance() { console.log('closing database'); databaseInstance = null; } return { open: createIntance, close: closeIntance } } const database = DatabseConnection(); database.open(); //Open database #1 database.open(); //Open database #1 database.open(); //Open database #1 database.close(); //close database
5、工廠模式
這個模式的創新之處在於,它不需要建構函式就能建立物件。它提供了用於建立物件的通用介面,我們可以在其中指定要建立的工廠(factory)物件的型別。這樣一來,我們只需指定物件,然後工廠會例項化並返回這個物件供我們使用。當物件元件設定起來很複雜,並且我們希望根據所處的環境輕鬆地建立不同的物件例項時,使用工廠模式就是很明智的選擇。在處理許多共享相同屬性的小型物件,以及建立一些需要解耦的物件時也可以使用工廠模式。
示例:
// 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));
6、觀察者模式
觀察者(observer)設計模式在許多物件同時與其他物件集通訊的場景中用起來很方便。在觀察者模式中不會在狀態之間發生不必要的事件 push 和 pull;相比之下,所涉及的模組僅會修改資料的當前狀態。
示例:
function Observer() { this.observerContainer = []; } Observer.prototype.subscribe = function (element) { this.observerContainer.push(element); } // 下面是從 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); }); }
7、命令模式 最後介紹的是命令(command)模式。命令設計模式將方法呼叫、操作或請求封裝到單個物件中,以便我們可以自行傳遞方法呼叫。命令設計模式讓我們可以從任何正在執行的命令中發出命令,並將責任委託給與之前不同的物件。這些命令以 run() 和 execute() 格式顯示。
(function(){ var carManager = { // 請求的資訊 requestInfo: function( model, id ){ return "The information for " + model + " with ID " + id + " is foo bar"; }, // 現在購買這個 car buyVehicle: function( model, id ){ return "You have successfully purchased Item " + id + ", a " + model; }, // 現在 arrange viewing arrangeViewing: function( model, id ){ return "You have successfully booked a viewing of " + model + " ( " + id + " ) "; } }; })();
小結
如果你覺得這篇文章不錯,請別忘記點個贊
跟關注
哦~