開發人員都應該瞭解的 7 種 JavaScript 設計模式

雲棲號資訊:【點擊查看更多行業資訊
在這裏您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!

開發人員將 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 &gt; -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 + " ) ";
}
};
})();

小結
對於 JavaScript 開發人員來說,使用設計模式的好處很多。設計模式的一些主要優點包括提升項目的可維護性,還能減少開發週期中不必要的工作。JavaScript 設計模式可以爲複雜的問題提供解決方案,提升開發速度並提高生產率。但並不能說這些設計模式就可以讓開發人員偷懶了。

【雲棲號在線課堂】每天都有產品技術專家分享!
課程地址:https://yqh.aliyun.com/zhibo

立即加入社羣,與專家面對面,及時瞭解課程最新動態!
【雲棲號在線課堂 社羣】https://c.tb.cn/F3.Z8gvnK

原文發佈時間:2020-06-30
本文作者:Deven
本文來自:“InfoQ ”,瞭解相關信息可以關注“[InfoQ](https://www.infoq.cn/article/jUDjSPGGcZx7FKKhWUcc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章