โ Kembali ke Design Pattern
๐
Behavioral
Template Method
Mendefinisikan kerangka algoritma di base class, sementara langkah-langkah tertentu diserahkan ke subclass.
Masalahnya
Beberapa class mengimplementasikan algoritma yang strukturnya sama tetapi langkahnya berbeda. Kode kerangka yang sama terduplikasi di setiap class.
Cara Kerja
- โบBase class mendefinisikan kerangka algoritma, yaitu urutan langkah secara keseluruhan
- โบSubclass meng-override langkah tertentu tanpa mengubah struktur keseluruhan
- โบfinal pada template method mencegah subclass mengubah urutannya
- โบHook method adalah override opsional yang menyediakan titik perluasan
- โบHollywood Principle: "Don't call us, we'll call you", base class yang mengendalikan alurnya
Kapan Digunakan
โBeberapa class berbagi struktur algoritma yang sama dan hanya beberapa langkahnya berbeda
โKode framework yang memanggil langkah buatan pengguna di titik tertentu
โMenghilangkan duplikasi kode di antara class yang mirip
โPipeline pemrosesan data: fetch โ parse โ format โ store
Contoh di Dunia Nyata
๐
iOS
UIViewController lifecycle (viewDidLoad, viewWillAppear, viewDidAppear), UIView draw(_:)
๐ค
Android
Fragment lifecycle (onCreate, onCreateView, onResume), Activity onCreate flow
๐
Web
React component lifecycle, Express route handler flow, Jest test lifecycle (beforeEach / afterEach)
Contoh Kode
Swift
class ReportGenerator {
// Template method โ final so subclasses can't change the sequence
final func generate() -> String {
let data = fetchData()
let parsed = parseData(data)
let report = formatReport(parsed)
return report
}
func fetchData() -> String { "raw:server" }
func parseData(_ raw: String) -> [String] { [raw] }
func formatReport(_ items: [String]) -> String { items.joined(separator: "\n") }
}
class JSONReport: ReportGenerator {
override func parseData(_ raw: String) -> [String] { ["JSON:\(raw)"] }
override func formatReport(_ items: [String]) -> String {
"{\(items.joined(separator: ","))}"
}
}
class CSVReport: ReportGenerator {
override func formatReport(_ items: [String]) -> String {
items.joined(separator: ",")
}
}
print(JSONReport().generate()) // {JSON:raw:server}
print(CSVReport().generate()) // raw:server