天天看點

開發人員都應該了解的 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

繼續閱讀