
泡泡麵的流程是什麼?打開蓋子 → 放調味包 → 加熱水 → 等三分鐘。不管你泡的是辛拉麵還是花雕雞麵,這個流程都一樣——差別只在「調味包裡是什麼」。
Template Method Pattern 就是這個道理。
先講結論
父類別定義流程骨架(load → validate → parse → output),子類別只覆寫「不同的部分」。流程不會被子類別搞亂,但每一步的細節可以自由發揮。
classDiagram class DataProcessor { <<abstract>> +process(data) any +loadData(data)* any +validateData(data)* any +parseData(data)* any +outputResult(data) any } class CSVDataProcessor { +loadData(data) any +validateData(data) any +parseData(data) String[] } class JSONDataProcessor { +loadData(data) any +validateData(data) any +parseData(data) Object } DataProcessor <|-- CSVDataProcessor DataProcessor <|-- JSONDataProcessor note for DataProcessor "process() 定義固定流程\n子類別覆寫各步驟"
實戰:資料處理管線
處理 CSV 和 JSON 的步驟其實一模一樣,只是 parse 的方式不同。如果你寫了兩套完整的處理流程,那九成的 code 是重複的。

class DataProcessor {
// 這就是 template method——流程骨架,子類別不能改
process(data) {
const loaded = this.loadData(data);
const validated = this.validateData(loaded);
const parsed = this.parseData(validated);
return this.outputResult(parsed);
}
loadData(data) { throw new Error('請實作 loadData'); }
validateData(data) { throw new Error('請實作 validateData'); }
parseData(data) { throw new Error('請實作 parseData'); }
// hook method:子類別可以覆寫,也可以不覆寫
outputResult(data) { return data; }
}
class CSVDataProcessor extends DataProcessor {
loadData(data) {
console.log('載入 CSV...');
return data;
}
validateData(data) {
console.log('驗證 CSV 格式...');
return data;
}
parseData(data) {
return data.split(',');
}
}
class JSONDataProcessor extends DataProcessor {
loadData(data) {
console.log('載入 JSON...');
return data;
}
validateData(data) {
console.log('驗證 JSON 格式...');
return data;
}
parseData(data) {
return JSON.parse(data);
}
}
const csv = new CSVDataProcessor();
csv.process('a,b,c,d'); // 走同一套流程,用 CSV 的方式 parseTemplate Method vs Strategy
兩個都在處理「演算法可替換」,但方向相反:
- Template Method:用繼承,父類別控制流程
- Strategy:用組合,外部注入策略
如果你的流程骨架是固定的、只有個別步驟需要替換——用 Template Method。如果整個演算法都要替換——用 Strategy。
Template Method 就像 SOP 手冊——流程寫死在那,你只需要填空。問題是有些人填空也能寫出讓你看不懂的東西。