設計模式在JavaScript中用於在JavaScript的Web項目中解決一些常見問題的可重複解決方案。javascript
JavaScript設計模式是很是適合做爲一種模式去提供問題的解決方案,但這並不能表明能夠替代開發人員。java
結合開發人員的經驗,設計模式能夠幫助優化咱們的代碼,而且尋求問題的解決方案和提供經常使用的解決方案,而不是片面的代碼和語法。數據庫
JavaScript設計模式能夠協助開發人員寫出有組織、優秀且良好結構的代碼。
設計模式在使用中雖然很容易出現重複的狀況,但卻歷來沒法取代開發人員,相反,設計模式只能經過提供與指定問題關係不大的解決方案去防止開發中的大問題背景下的小問題,從而爲開發人員提供幫助。設計模式
設計模式經過消除沒必要要的重複代碼來減小總體代碼體積,從而使得咱們書寫的代碼更加健壯。bash
在本文中,我將介紹7種優秀、更受歡迎的JavaScript設計模式,它們總體屬於三大類,建立型模式、結構型模式和行爲型模式;app
這算得上是一種特殊的模式,它主要用於分配內存後初始化新建立的對象。
因爲JavScript是一種面嚮對象語言,其每時每刻不在處理對象,所以我首先研究這個模式。ssh
一下是建立構造函數模式的一種寫法。函數
var newObject = {}
var newObject = Object.create(Object.prototype)
var newObject = newObject()
複製代碼
const object = new ConstructorObject();
複製代碼
關鍵字new
告訴Javascript,ConstructorObject
應當是一個構造函數。
在這個模式中是不支持繼承的。測試
原型模式是基於原型繼承的,其建立的對象會充當其餘對象的原型。其實,在創造對象時原型充當的是一個藍圖的角色。
示例優化
var myCar = {
name: 'Ford Escort',
brake: function() {
console.log('stop! I am applying branks');
},
Panic: function() {
console.log ( 「wait. how do you stop thuis thing?」);
}
}
// 建立一個car實例
var youCar = Object.create(myCar);
console.log(youCar.name); // Ford Escort
複製代碼
在模塊設計模式中,是在原型模式上的一個改進。在模塊模式中設置了不一樣類型的修飾符(私有/共有)。能夠建立類似的函數或屬性而不會引發衝突。這在命名上具備靈活性,很差的是沒法覆蓋外部建立的函數。
示例
function AnimalContainer() {
const container = [];
function addAnimal(name) {
container.push(name);
}
function getAllAnimal() {
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: getAllAnimal,
remove: removeAnimal
}
}
const container = AnimalContainer();
// 添加
container.add('Hen');
container.add('Goat');
container.add('Sheep');
// 獲取
console.log(container.get()); // ['Hen', 'Goat', 'Sheep']
// 移除
container.remove('Sheep');
console.log(container.get()); // ['Hen', 'Goat']
複製代碼
當只須要建立一個實例時,好比數據庫的鏈接,這一模式仍是很友好的。僅僅建立一個實例,當你肯定關閉鏈接或者打開實例時,確保已經關閉了以前的實例。這種模式也常常被稱爲嚴格模式,伴隨着這種模式的一個缺點就是在測試時不友好,由於在測試時很難發現其依賴的隱藏起來的對象。
示例
function DatabaseConnection() {
let databaseInstance = null;
// 追蹤在特定時間下建立的實例數
let count = 0;
function init() {
console.log(`opening database!#${count++}`);
}
function createInstance() {
if (databaseInstance === null) {
databaseInstance = init();
}
return databaseInstance;
}
function closeInstance() {
console.log('closing databse');
databaseInstance = null;
}
return {
open: createInstance,
close: closeIntance
}
}
const database = DatabaseConnection();
// 僅僅建立一個實例
database.open(); // opening database!#1
database.open(); // opening database!#1
database.open(); // opening database!#1
database.open(); // opening database!#1
database.close(); // close database
複製代碼
這種模式一個建立對象的革新,再也不須要構造函數。它提供了一個通用的接口來建立對象,而且咱們還能夠指定須要建立的工廠對象的類型。所以,咱們僅僅指定對象,工廠對象實例化並返回供咱們使用。同時當對象組件具備較爲複雜時而且咱們想要根據不一樣的環境去建立不一樣的對象時,使用工廠模式時很是明智的。當使用許多須要共享的屬性的輕對象以及組成須要解耦的對象時,咱們也可使用工廠模式。
示例
// Dealer A
DealerA = {};
DealerA.title = function title() {
return 'Dealer A';
}
DealerA.pay = function pay(amount) {
console.log('配置用戶名: ${this.username} 密碼: $ { this.password }');
return <code>Payment for service $${amount} is successful using ${this.title()}</code>;
};
// Dealer B
DealerB = {};
DealerB.title = function title() {
return 'DealerB';
}
DealerB.pay = function pay(amount) {
console.log('配置用戶名: ${this.username} 密碼: $ { this.password }');
return <code>Payment for service $${amount} is successful using ${this.title()}</code>;
}
function DealerFactory(DealerOption, config = {}) {
const dealer = Object.create(DealerOption);
Object.assign(dealer, config);
return dealer;
}
const dealerFactory = DealerFactory(DealerA, {
username: 'user',
password: 'password'
});
console.log(dealerFactory.title());
console.log(dealerFactory.pay(12));
const dealerFactory2= DealerFactory(DealerB, {
username: 'user',
password: 'password'
});
console.log(dealerFactory2.title());
console.log(dealerFactory2.pay(99));
複製代碼
觀察者模式在對象與其餘對象集合通訊的時候使用仍是很方便的。在這個模式中,狀態之間沒有沒必要要的push
和pull
操做,其所設計的模塊僅修改數據的當前狀態。
示例
function Observer() {
this.observerContainer = [];
}
Observer.prototype.subscribe = function (element) {
this.observerContainer.pssh(element);
}
// 從容器中移除一個元素
Observer.prototype.unsubscribe = function (element) {
const index = this.observerContainer.indexOf(element);
if (index !== -1) {
this.observerContainer.splice(index, 1);
}
}
Observer.prototype.notifyAll = function (element) {
this.observerContainer.forEach(function (observerElement) {
observerElement(element);
});
}
複製代碼
在最後,我用命令模式結束了我對JavaScript設計模式的7種最佳總結。命令模式將方法的調用、操做或請求都封裝到一個對象之中,便於咱們去思考地去調用。命令模式使咱們能夠向正在執行的命令發佈命令,並將責任委託到不一樣的對象中。這些命令都以run()
、execute()
格式展現。
示例
(function () {
var carManager = {
requestInfo: function (model, id) {
return `the infomation for ${model} with ID ${id} is foo bar`;
},
buyVehicle: function (model, id) {
return `You have successfully purchased Item ${id}, a ${model}`;
},
arrangeViewing: function (model, id) {
return `You have successfully booked a viewing of ${model} (${id})`
}
};
})();
複製代碼
對於咱們JavaScript開發人員來講,這幾種設計模式仍是頗有用的,維護性高的項目和減小開發週期中沒必要要的工做是設計模式的主要優勢。雖然JavaScript設計模式能夠爲複雜的問題提供解決方案和思路,可是設計模式代替開發人員的結論還是不恰當的。
在平常開發工做中,我經常使用命令模式,而其餘模式雖然能夠用到,但並不頻繁。對於大多數開發者來講,設計模式僅僅是提供了一種特定情景下的解決方案罷了,同時順便也擴展了本身的思路。同時翻譯不妥的地方還請指正,之後的翻譯中會更加努力:)