在父類定義一個演算法的「骨架」,把其中會變的步驟留成抽象方法或 hook,交給子類去 override。核心是固定流程的順序與不變部分,只開放特定步驟給子類客製——是「繼承版的 Strategy」。
🧠 When to Use
TIP
訊號:好幾個流程「大架構一模一樣、只有中間幾步不同」,你正想複製整段流程再各自改幾行——這正是要把骨架上提的時機。
- 多個演算法整體流程相同,只有少數步驟有差異。
- 想把不變的流程順序集中在一處,避免子類各自複製、各自走偏。
- 想提供可選的 hook,讓子類選擇性地插手某些環節。
⚖️ Structure & Variants
經典版 — 父類定骨架,抽象步驟留給子類
abstract class DataProcessor {
fun run() { // ← template method,骨架固定
val raw = read()
val result = process(raw)
write(result)
if (shouldLog()) println("done") // hook,可選覆寫
}
protected abstract fun read(): String
protected abstract fun process(data: String): String
protected abstract fun write(data: String)
protected open fun shouldLog() = false // 預設行為
}
class CsvProcessor : DataProcessor() {
override fun read() = "a,b,c"
override fun process(data: String) = data.uppercase()
override fun write(data: String) { /* ... */ }
}run()通常設成final,子類不能改流程順序,只能填空。
Hook 方法 — 給子類可選的插點
- 抽象方法是「必填」,hook(帶預設實作的
open方法)是「選填」。 - 子類靠覆寫 hook 微調行為,不覆寫就走父類預設。
和 Strategy 的差別(繼承 vs 組合)
- Template Method:用繼承,可變步驟靠子類 override,流程綁在父類、編譯期決定。
- Strategy:用組合,可變步驟靠注入物件,執行期可換。
- 規則:步驟少、靜態、共用骨架多 → Template Method;要執行期切換、避免繼承僵化 → Strategy。
⚠️ Misuse & Anti-patterns
- 繼承層級越疊越深:為了複用骨架一路往下繼承,耦合與脆弱性暴增;多數情況優先考慮組合(Strategy)。
- 把太多步驟開成抽象:骨架幾乎空殼,子類得實作一大半,反而失去「固定流程」的價值。
- 子類偷改流程:template method 沒設
final,子類覆寫掉整個run(),骨架形同虛設。
🔑 Takeaways
- 本質是「父類定流程骨架、子類填可變步驟」,把不變的順序集中、防止子類各自走偏。
- 抽象方法是必填、hook 是選填;template method 記得設
final。 - 是繼承版的 Strategy;要執行期切換或怕繼承僵化,就改用組合。
No notes yet — jot your takeaways or Q&A here.