軟體設計

Swift 靜態工廠:為什麼用 make 取代 init

Swift 靜態工廠方法可透過名稱表達建立意圖,並控制回傳型別、快取與實例重用。本文整理選擇 static func make 而非 init 的優缺點,以及它與 GoF 模式的差異。

閱讀 4 分鐘
Swift 靜態工廠:為什麼用 make 取代 init 封面圖

進行 iOS 開發時,你可能曾在別人的程式碼中看到 init(...) 而不是 static func make(...),感到疑惑。

先說結論。

Swift 靜態工廠方法能替建立流程命名、彈性調整回傳型別,還能控制物件重用;當只用 init 不夠靈活時,就可以派上用場。

今天從實務角度逐一說明為什麼用 static func make 取代 init。

本文的靜態工廠只是在名稱上類似 GoF Factory Method Pattern;該模式由子類別決定建立方式。更多 Swift 實作範例請見 使用工廠函式分離建立邏輯的方法,GoF 模式的界線則請見 工廠方法 vs. 抽象工廠。


靜態工廠方法究竟是什麼?

名稱聽起來很厲害,但概念很簡單。

這是會建立並回傳物件的 static 方法。不直接呼叫建構子,而是加上一個包住建立流程的函式。

大致如下。

struct Button {
    let title: String
    let style: Style

    // init外包一層的靜態工廠方法
    static func makePrimary(title: String) -> Button {
        Button(title: title, style: .primary)
    }
}

呼叫端會像這樣:Button.makePrimary(title: "확인")。

結果和直接呼叫 Button(title:style:) 相同,只是從名稱就能看出「要建立哪個按鈕」。

這個小差異在實務上影響不小。


改用 make 取代 init 的 4 個理由

以下是我在實際專案中感受到的優點。

1. 用名稱表達意圖

建構子的名稱全部都是 init,只能靠參數組合區分。

因此,類似的 init 一多就容易混淆。加上 make(fromJSON:)、make(withDefaults:) 這類名稱後,只看呼叫端也能知道建立的是什麼。

2. 不必每次都建立新物件

每次呼叫 init 都一定會建立新實例。

相較之下,工廠方法可以回傳快取物件或既有的單例。像 Bool 的真假值這類固定值,重用會有效率得多。

3. 回傳型別更有彈性

我個人覺得這是最強大的優點。

工廠方法可以回傳宣告型別的子型別或協定實作。呼叫端不必知道具體型別。

protocol Shape { func area() -> Double }

enum ShapeFactory {
    // 依條件回傳不同實作
    static func make(sides: Int) -> Shape {
        sides == 4 ? Square() : Triangle()
    }
}

make(sides:) 的回傳型別只有一個 Shape,但實際會產生符合情境的實作。

表面上是一個 Shape,內部型別會依情況不同
表面上是一個 Shape,內部型別會依情況不同

4. 可以更平順地處理失敗

雖然可以使用 init? 或 throws,但工廠方法很適合直接回傳選用型別,或用 Result 包裝結果。建立邏輯複雜時,流程會更清楚。

只加一行 make,呼叫端立刻清楚許多
只加一行 make,呼叫端立刻清楚許多

和 init 有什麼不同?一眼比較

怕容易混淆,所以整理成表格。

分類 init(建構子) static func make(靜態工廠)
名稱 固定為 init 可自由命名
新實例 每次強制建立 可重用、可快取
回傳型別 只能是自身型別 可為子型別或協定
失敗處理 init? / throws 選用型別、Result 等皆可
缺點 無法用名稱區分 限制子類別化,探索性較低

缺點也坦白說明一下。

如果只有工廠方法而沒有 public init,這個型別就很難透過繼承擴充。

建構子會直接出現在自動完成中,但要找 make 通常得先知道名稱,因此探索性稍低。建議使用 make、create、from 這類慣例名稱。


那麼什麼時候該用?

我在實務上的判斷方式如下。

  1. 只需填入儲存屬性 → 直接用 init
  2. 建立方式有多種,想用名稱區分 → make
  3. 需依條件回傳不同型別 → make
  4. 想重用或快取物件 → make
我用這張判斷表決定兩者該選哪個
我用這張判斷表決定兩者該選哪個

總結來說,當建立不只是「填入值」,而是成為一個決策流程時,工廠方法就能發揮價值。

反過來,所有建立都包成 make,程式碼反而會變冗長。重點是只在需要時使用。

一開始可能不習慣,但掌握意圖後,讀程式碼會變得更有趣。下次遇到類似情況,不妨試試 make,相信會有幫助 🙂

推薦文章