iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0

工廠方法是建立型模式,它提供一個物件建立方法,讓客戶不需透過具體類別就能建立物件。

生活案例

想像你在路邊的自動販賣機買飲料,只要選取想要的品項,再投入對應的金額,自動販賣機便會給你想要的商品。工廠方法模式就像一台自動販賣機一樣,只要告訴它你要什麼,它就會生產對應的產品給你。你不需要知道這些商品如何製作,來自哪裡,自動販賣機自會處理好一切。

舉個例子

幾天前,老闆談到了一個新案子。這次客戶來自美容產業,他們非常重視企業形象,甚至提供了一套設計系統,要求網頁中的所有元素都符合這套規範。為了滿足客戶的需求,你提議為他們量身打造一套元件庫,其中必須包含所有常用的 UI 元件,如按鈕、輸入框和下拉選單。

幸運的是,你的同事中有一位切版高手,他只用了幾天時間就把所有元件都製作完成。然而,這些元件多達數十個,要讓每位成員熟記這些元件的命名和路徑得花上好一段時間,可能比製作元件的時間還長。主管要求你想出一個方法來統一元件的建立方式。

這有什麼難的呢?只要替每個元件取一個名稱,再透過元件名稱指定要建立的元件即可。我們還可以建立元件對照表避免永無止盡的 if else 判斷式。就這樣,你輕鬆地完成了主管交辦的任務,而主管也對你的表現非常滿意。

const beautyComponentMap = {
  button: BeautyButton,
  input: BeautyInput,
  menu: BeautyMenu,
  // ...
};

function createBeautyComponent(type: keyof typeof beautyComponentMap) {
  return new beautyComponentMap[type]();
}

const button = createBeautyComponent("button");
const input = createBeautyComponent("input");

在那之後,案子順利地結束,客戶對交付的成果十分滿意。幾個月後,老闆宣布了一個新案子。這次的客戶是一家電動車代理商,他們希望我們打造一個充滿現代感的官方網站。

由於上次打造元件庫的經驗非常成功,主管決定如法炮製,為客戶製作一套現代感十足的元件庫。雖然需要打造全新的元件庫,但我們有許多程式碼可以重複利用。比如說,我們可能需要設定元件的屬性或將元件添加至網頁中。我們可以使用工廠模式來封裝通用的程式碼,然後由子類別來決定要產生哪些元件。

工廠方法模式在父類別中定義了物件的建立方法,並讓子類別決定要建立什麼物件、如何建立。使用工廠模式的子類別不僅能實現自訂的建立方法,還能使用父類別的通用方法。

我們來使用工廠方法改寫美容元件庫。首先,定義元件庫的通用介面 UILibrary ,接著再繼承 UILibrary 實作美容元件庫。

abstract class UILibrary<
  ComponentMap extends Record<string, new () => Component>
> {
  instantiate<T extends keyof ComponentMap>(type: T, options?: {}) {
    const component = this.create(type);
    component.setOptions(options);
    return component;
  }

  abstract create<T extends keyof ComponentMap>(
    type: T
  ): InstanceType<ComponentMap[T]>;
}

class BeautyUILibrary extends UILibrary<BeautyComponentMap> {
  create<T extends keyof BeautyComponentMap>(type: T) {
    const Component = beautyComponentMap[type];
    return new Component() as InstanceType<BeautyComponentMap[T]>;
  }
}

如此一來,美容元件庫既能擁有自訂的元件建立方法,還可以使用定義在父類別的通用方法,往後我們也能透過繼承輕鬆地打造更多元件庫。

文中分享了兩段範例程式碼,第一段程式碼是簡單工廠模式,第二段則使用了工廠方法模式。簡單工廠模式將物件的建立過程封裝起來以簡化客戶端的程式碼;工廠模式則透過繼承提供更有彈性的設計方式。這兩種模式皆有助於簡化客戶端的程式碼,前者提供簡單直覺的解決方案,後者則適合運用在更為複雜的設計情境。

定義

Factory Method Pattern

  • 抽象類別(Creator): 定義工廠方法和其他通用方法
  • 具體類別(ConcreteCreator): 繼承通用方法並實作工廠方法的具體細節

工廠方法模式在父類別中定義工廠方法,由子類別實作具體細節。父類別負責提供建立物件的介面或預設方法,而子類別則根據需求決定要建立哪些物件以及如何建立。

由於工廠方法封裝了物件的建立細節,客戶只需使用工廠方法建立物件,而不需知道物件如何被建立的。這不僅簡化了客戶端的程式碼,還有助於統一物件的建立邏輯。

總結

  • 工廠方法封裝了建立物件的細節以簡化客戶端程式碼
  • 子類別能實現自訂的建立方法來決定要建立的物件以及如何建立
  • 工廠方法有助於統一客戶端的物件建立邏輯
  • 簡單工廠模式提供簡單直覺的解決方案;工廠方法模式則適合運用在更為複雜的設計情境

完整範例

https://github.com/chengen0612/design-patterns-typescript/blob/main/patterns/creational/factory-method.ts


上一篇
Day 04 - 堅若磐石 SOLID
下一篇
Day 06 - Strategy 策略
系列文
前端也想學設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言