JS 工廠模式

SHERlocked93發表於2017-12-14

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. 總結

那麼什麼時候使用工廠模式呢,以下幾種情景下工廠模式特別有用:

  • 物件的構建十分複雜
  • 需要依賴具體環境建立不同例項
  • 處理大量具有相同屬性的小物件

什麼時候不該用工廠模式:
不濫用運用工廠模式,有時候僅僅只是給程式碼增加了不必要的複雜度,同時使得測試難以執行下去。


本文是系列文章,可以相互參考印證,共同進步~

  1. JS 抽象工廠模式
  2. JS 工廠模式
  3. JS 建造者模式
  4. JS 原型模式
  5. JS 單例模式
  6. JS 回撥模式
  7. JS 外觀模式
  8. JS 介面卡模式
  9. JS 利用高階函式實現函式快取(備忘模式)
  10. JS 狀態模式
  11. JS 橋接模式
  12. JS 觀察者模式

網上的帖子大多深淺不一,甚至有些前後矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出~

參考:
深入理解JavaScript系列(28):設計模式之工廠模式
《JS 模式》
《Javascript 設計模式》 - 張榮銘

相關文章