1. 簡介
工廠模式的目的是為了建立物件,它通常在類或者類的靜態方法中實現,具有以下目標:
- 當建立相似物件時執行重複操作
- 當編譯時不知道具體型別的情況下,為工廠客戶提供一個建立物件的介面
與建立型模式類似,工廠模式建立物件(視為工廠裡的產品)時無需指定建立物件的具體類。
工廠模式定義一個用於建立物件的介面,這個介面由子類決定例項化哪一個類。該模式使一個類的例項化延遲到了子類。而子類可以重寫介面方法以便建立的時候指定自己的物件型別。
這個模式十分有用,尤其是建立物件的流程賦值的時候,比如依賴於很多設定檔案等。並且,你會經常在程式裡看到工廠方法,用於讓子類類定義需要建立的物件型別。
2. 實現
一個簡單的實現,使用IIFE:
var Car = (function () {
var Car = function (model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
};
return function (model, year, miles) {
return new Car(model, year, miles);
};
})();
var tom = new Car("Tom", 2009, 20000);
var dudu = new Car("Dudu", 2010, 5000);
如果使用物件屬性來實現:
var productManager = {};
productManager.createProductA = function() {
this.prd = 'A'
console.log('Product ' + this.prd);
}
productManager.createProductB = function() {
this.prd = 'B'
console.log('Product ' + this.prd);
}
productManager.factory = function(typeType) {
return new productManager[typeType];
}
productManager.factory("createProductA"); // Product A
productManager.factory("createProductB"); // Product B
以下例子中的工廠方法接受在執行時以字串形式指定的型別,然後建立並返回所請求型別的物件。
function CarMaker() {}
CarMaker.prototype.drive = function() {
return `I have ${this.doors} doors!`
}
CarMaker.factory = function(type) {
const constr = type
if (typeof CarMaker[constr] !== 'function') {
throw new Error(`${constr} doesnot exist`)
}
// 原型繼承的方式使得原型繼承父類
if (typeof CarMaker[constr].prototype.drive !== 'function') {
CarMaker[constr].prototype = new CarMaker()
}
return new CarMaker[constr]()
}
CarMaker.Compact = function() { this.doors = 4}
CarMaker.Convertible = function() { this.doors = 2}
const corolla = CarMaker.factory('Compact')
corolla.drive() // "I have 4 doors!"
也可以把實際物件的建立工作放到原型中:
const Factory = function(type, content) {
return (this instanceof Factory)
? new this[type](content)
: new Factory(type, content)
}
Factory.prototype.Compact = function(content) { this.doors = 4}
Factory.prototype.Convertible = function(content) { this.doors = 2}
Factory.prototype.Compact.prototype.drive = function() {
return `I have ${this.doors} doors!`
}
const corolla = Factory('Compact')
corolla.drive() // "I have 4 doors!"
3. 總結
那麼什麼時候使用工廠模式呢,以下幾種情景下工廠模式特別有用:
- 物件的構建十分複雜
- 需要依賴具體環境建立不同例項
- 處理大量具有相同屬性的小物件
什麼時候不該用工廠模式:
不濫用運用工廠模式,有時候僅僅只是給程式碼增加了不必要的複雜度,同時使得測試難以執行下去。
本文是系列文章,可以相互參考印證,共同進步~
網上的帖子大多深淺不一,甚至有些前後矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出~
參考:
深入理解JavaScript系列(28):設計模式之工廠模式
《JS 模式》
《Javascript 設計模式》 - 張榮銘