有一個類別包山包海:欄位一大票、方法幾百個、什麼流程都經過它。改任何小需求都得動它,動它又到處出事。這是 God Object(上帝物件)——辨識它、然後怎麼拆?
🎯 Scenario
// 一個 OrderManager 同時扛下驗證、計價、庫存、金流、通知、持久化……
class OrderManager {
fun validate(order: Order) { /* ... */ }
fun calculatePrice(order: Order): Int { /* ... */ }
fun reserveStock(order: Order) { /* ... */ }
fun charge(order: Order) { /* ... */ }
fun sendConfirmation(order: Order) { /* ... */ }
fun save(order: Order) { /* ... */ }
// ...再過半年,方法破百、欄位破百
}
壞味道:臃腫介面(公開成員過多)+臃腫實作(方法多且複雜)。書中的極端真實案例 java.awt.Component 有 332 個方法、107 個欄位、上萬行——所有方法的循環複雜度總和 1143。集中式控制讓這個類別成為系統的單點腐化源。
🧠 Intuition
TIP
先別看下面。問自己:這個類別有「幾個會要求它改變的人(actor)」?驗證規則、計價策略、金流串接、通知渠道——它們會不會各自因不同理由而變?如果答案是「會」,那它承擔了幾個職責?
⚖️ Reference Design
先分辨:它是『責任太多』還是『單純太大』?
書中把兩種味道分清楚——它們常同時出現但不等同:
| 味道 | 違反 | 焦點 |
|---|---|---|
| Multifaceted Abstraction | SRP | 一個抽象多個責任 |
| Insufficient Modularization | 分解原則 | 一個抽象過大、過於複雜 |
- 「一個類別可以只有一個責任但實作很龐大;也可以很小卻扛多個責任。」先判斷你的 God Object 屬於哪一種(多半兩者兼有)。
解法:沿變更軸線把職責切出去
// 沿『誰會要求改』把 OrderManager 拆成一組協作者
class OrderValidator { fun validate(order: Order) { /* ... */ } }
class Pricing { fun calculate(order: Order): Int { /* ... */ } }
class Inventory { fun reserve(order: Order) { /* ... */ } }
class PaymentGateway { fun charge(order: Order) { /* ... */ } }
class Notifier { fun confirm(order: Order) { /* ... */ } }
class OrderRepository{ fun save(order: Order) { /* ... */ } }
// OrderService 只負責『編排』,把工作委派出去(瘦身後的協調者)
class OrderService(
private val validator: OrderValidator,
private val pricing: Pricing,
private val inventory: Inventory,
private val payment: PaymentGateway,
private val notifier: Notifier,
private val repo: OrderRepository,
) {
fun place(order: Order) {
validator.validate(order)
val total = pricing.calculate(order)
inventory.reserve(order)
payment.charge(order)
repo.save(order)
notifier.confirm(order)
}
}🔑 Takeaways
- God Object = 臃腫介面 + 臃腫實作,是集中式控制的產物、系統的單點腐化源。
- 辨識靠「幾個 actor 會要求它改」;解法是沿變更軸線用 SRP 拆職責、組合注入。
- 拆完的協調者只做編排;胖介面再用 ISP 收斂。
No notes yet — jot your takeaways or Q&A here.