使用 Swift 製作 App 時,初始化程式碼不知不覺就會變成這個樣子。
User(name:age:email:phone:address:isVerified:profileURL:createdAt:)
括號裡有 8 個參數。
看著呼叫端的程式碼,你得逐一用眼睛數,才能確認哪個值是 email、哪個是 phone。
這種情況在 side project 中也很常見,但用 Swift Builder Pattern 整理後就能俐落解決。
先說結論,將參數很多的初始化改成用 Builder Pattern「一行設定一個」,可讀性會大幅提升。不必記住順序,也不用勉強用 nil 填入未使用的值。
先整理這篇文章可以帶走的重點。
- 為什麼 8 個參數的 init 容易出錯
- Builder Pattern 如何解決這個問題
- Swift 中實際使用的程式碼形式
- 何時該使用、何時該避免這個模式
8 個參數的 init,為什麼像地獄?
參數只有 3、4 個時,其實不太會有問題。
問題會從參數數量增加後開始。
第一,容易搞錯順序。即使把 phone 放到 email 的位置,只要兩者都是 String,編譯器也抓不到。
第二,選用值會變得很凌亂。就連現在不用的值,也得用 nil, nil, nil 填上。
第三,呼叫端變得很長,很難一眼看出正在建立什麼物件。
參數越多,init 就越像一張「必須填滿空格的考卷」;空格越多,錯誤也會跟著增加。
把 phone 和 profileURL 的位置放反,可能會讓你花上一天以上除錯。型別相同時,這類錯誤真的很難察覺。
Builder Pattern 是什麼?
Builder Pattern 不會一次建立複雜物件,而是逐一填入值,最後再完成物件。
不要在初始化時傳入所有值,而是只選擇並設定需要的值,最後透過像 build() 這樣的方法取得完成的物件。
想像在餐廳點餐就很容易理解。不必一次喊出所有食材,而是逐項說:「麵包要全麥、起司加量、不要醬料。」
如果設定核心值的方法會回傳自身,就能像串接句點一樣進行 chaining。下面是最簡單的 Builder 形式。
final class UserBuilder {
private var name = ""
private var email: String?
// 設定值並 self回傳自身,讓 chaining 成為可能
func setName(_ v: String) -> Self { name = v; return self }
func setEmail(_ v: String) -> Self { email = v; return self }
func build() -> User { User(name: name, email: email) }
}
因為設定方法會回傳 Self,所以可以像 .setName(...).setEmail(...) 一樣串接。
Swift 中如何使用 Builder Pattern?
大家最想知道的,應該就是實際呼叫端會如何改變。
使用前面建立的 Builder 後,物件建立程式碼會變成這樣。
// 只設定需要的值,標示名稱並免去順序的顧慮
let user = UserBuilder()
.setName("李錫宇")
.setEmail("[email protected]")
.build()
// 不用在未使用的值填入 nil
如你所見,不必再在意順序。方法名稱本身就是標籤,從結構上避免把 phone 放進 email 位置這類錯誤。
不用的值只要不呼叫對應方法即可。
在 Swift 中,也常用 struct 而非 class 建立 Builder,或傳入 closure,在同一個區塊內完成設定。請依專案風格選擇。
Builder Pattern 何時該用、何時該避免
只因為看起來不錯就到處加入,反而只會增加程式碼。
我把自己的判斷整理成表格(以 2026 年為止的個人專案經驗為基礎)。
| 情況 | 建議 |
|---|---|
| 5 個以上參數,選用值很多 | Builder Pattern |
| 有多個相同型別的參數 | Builder Pattern |
| 2~3 個參數,全部必要 | 一般 init |
| 值單純且固定 | 一般 init |
總結來說,參數少且全部必要時,沒有必要特地建立 Builder。
相反地,如果是混合許多選用值的大型物件,Builder 確實方便許多。
Q. 建立 Builder 後,程式碼不會變得更多嗎?
沒錯。Builder class 本身會增加程式碼。不過,如果這個物件會在多個地方建立,呼叫端變乾淨所帶來的好處更大。
Q. Swift 有預設參數,不能直接用那個嗎?
參數只有 3、4 個時,使用預設參數就足夠了。當參數很多、組合也多樣時,Builder 的優點才會真正發揮。
如果你正因為 8 個參數的 init 而感到壓力,不妨只在那個地方試用 Builder Pattern。不必全部重寫,從最複雜的一個物件開始,負擔會小很多。祝你今天也寫程式愉快!

