前端設計模式:工廠模式(Factory)

image.png


00、基礎概念

🚩工廠模式封裝了對象的創建new(),將消費者(使用)和生產者(實現)解耦。

工廠是幹什麼的?工廠是生產標準規格的商品的地方,建好工廠,投入原料(參數),產出特定規格的產品。so,工廠模式就是把對象的創建 —— new() 封裝起來,在工廠裏實現對象的創建(商品的生產)。這樣做的好處是用來解耦,解耦對象的消費(使用)和創建(實現),面向抽象編程(這個用到TS中的接口類型)。

✅使用場景

  • Vue中的createElement('h'); createElement('div')創建虛擬Dom;vue-router 中的路由基於模式mode創建不同的路由對象。
  • 多個同類對象的創建,創建過程複雜,而使用者不用關注創建、實現過程,只管拿到實例來使用。就像我們日常到超市購買商品,只管選擇使用,不用關注商品是怎麼生產的。

生產實例(商品)的工廠可以是小作坊,只生產少量簡單的商品,也可以是大型的複雜工廠,因此基於場景複雜程度又有多個工廠模式:

類別 說明
簡單工廠(Simple Factory) 小作坊,適用於少量對象的創建,集中式管理,使用簡單、擴展不便
工廠方法(Factory Method) 正規小工廠,每種產品一個獨立工廠,偏平化擴展
抽象工廠(Abstract Factory) 集團化大廠,產品種類、層級衆多,需要多層級的工廠來管理,代碼也稍複雜

實際掌握簡單工廠就差不多了,工廠方法、抽象工廠瞭解下即可。


01、簡單工廠(Simple Factory)

簡單工廠模式,也稱爲靜態工廠模式(Static Factory Method),由一個(靜態)類統一管理對象的創建,,根據一個簡單參數創建不同的示例對象。針對少量的、簡單的場景,在工廠中統一實現所有商品的創建。如下示例,手機工廠提供多型號手機的創建,傳入手機型號參數即可。

示例代碼:

let HuaweiPhone = class { name = '華爲' }
let XiaomiPhone = class { name = '小米' }
// 手機生產工廠
class PhoneFactory {
  static create(type) {
    switch (type) {
      case 'huawei':
        return new HuaweiPhone()
      case 'xiaomi':
        return new XiaomiPhone()
      default:
        throw new Error(`不支持生產型號爲${type}的設備`)
    }
  }
}
// 使用,調用工廠方法創建對象實例
let p1 = PhoneFactory.create('xiaomi')
let p2 = PhoneFactory.create('huawei')
console.log({ p1, p2 })

上面版本代碼中,如果擴充其他型號,則需要修改工廠的代碼,不利於擴展,可以稍微改進下,支持動態新增創建對象實例的方法。

// 手機生產工廠
class PhoneFactory {
  // 實例對象創建器Map
  #constructors = new Map()
  constructor() {
    this.#constructors.set('huawei', () => new HuaweiPhone())
    this.#constructors.set('xiaomi', () => new XiaomiPhone())
  }
  // 可擴展型號
  add(type, func) {
    this.#constructors.set(type, func)
  }
  // 生產商品
  create(type) {
    const func = this.#constructors.get(type)
    if (func) {
      return func.call()
    }
    throw new Error(`不支持生產型號爲${type}的設備`)
  }
}
const phoneFactory = new PhoneFactory()
// 添加蘋果型號
let IPhone = class { name = '蘋果' }
phoneFactory.add('iphone', () => new IPhone())
// 使用,調用工廠方法創建對象實例
let p1 = phoneFactory.create('iphone')
let p2 = phoneFactory.create('huawei')

02、工廠方法(Factory Method)

簡單工廠是小作坊,產量有限,如果生產的型號很多,在一個地方管理所有的new() 操作,負擔很大,風險也很大。工廠方法(也叫工廠模式)就是爲每一個產品建立單獨的工廠,一個工廠只生產一類商品,這樣就可以靈活擴展,相互不影響了。

代碼示例:

let HuaweiPhone = class { name = '華爲' }
let XiaomiPhone = class { name = '小米' }

// 沒什麼用的工廠基類(JS中可以不要),用來抽象工廠接口
let IFactory = class { creat() { } }
// 華爲手機工廠
class HuaweiFactory extends IFactory {
  creat() {
    return new HuaweiPhone()
  }
}
// 小米手機工廠
class XiaomiFactory extends IFactory {
  creat() {
    return new XiaomiPhone()
  }
}
// 使用
const huaweiFactory = new HuaweiFactory()
let p1 = huaweiFactory.creat()
let p2 = huaweiFactory.creat()

在Java、C#語言中都會用接口進行抽象、約束,面向抽象編程,實現起來會比較清晰。JavaScript中就沒法抽象約束了,比較隨意,只能靠TypeScript了。


03、抽象工廠(Abstract Factory)

如果說簡單工廠是小作坊,工廠方法就是小工廠,那抽象工廠就是大型集團了,下屬多個產業鏈、多個工廠。

抽象工廠可以看做是簡單工廠+工廠方法的結合升級,增加了產品族的概念。還是用電子產品生產來舉例,比如一個大型電子產品工廠,有多個品牌產品,如華爲、小米,每個品牌的電子產品形成一個產品族,包含多個產品,如手機、平板、電視等等,不同品牌的產品也是不同的。因此一個產品工廠(如華爲工廠)就會有多條生產線,生產多個產品(手機、平板、電視)。

🚩基本結構:抽象工廠類+具體工廠類,抽象產品類+具體產品類組合。JS中沒有沒有抽象類、接口的概念,只能示意一下(或者TS),抽象工廠簡單瞭解即可,掌握上面的簡單工廠、工廠方法就差不多了。

示例代碼:

// 模擬手機抽象類
let IPhone = class { name = '手機' }
// 手機產品
let HuaweiPhone = class extends IPhone { name = '華爲' + this.name }
let XiaomiPhone = class extends IPhone { name = '小米' + this.name }

// 模擬電視抽象類
let ITV = class { name = '電視' }
// 電視產品
let HuaweiTV = class extends ITV { name = '華爲' + this.name }
let XiaomiTV = class extends ITV { name = '小米' + this.name }

// 模擬抽象工廠,含兩個抽象方法,生產手機、電視
let AbstractFactory = class { createPhone() { }; createTV() { } }
// 具體工廠:華爲工廠
class HuaweiFactory extends AbstractFactory {
  createPhone() {
    return new HuaweiPhone()
  }
  createTV() {
    return new HuaweiTV()
  }
}
// 具體工廠:小米工廠
class XiaomiFactory extends AbstractFactory {
  createPhone() {
    return new XiaomiPhone()
  }
  createTV() {
    return new XiaomiTV()
  }
}
// 使用
let xiaomiFactory = new XiaomiFactory()
let m1 = xiaomiFactory.createPhone();
let m2 = xiaomiFactory.createTV();
console.log(m1, m2) // XiaomiPhone {name: '小米手機'} XiaomiTV {name: '小米電視'}

參考資料


©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀

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