Template Method Pattern (Mẫu Template Method)
Định nghĩa (Definition)
Template Method định nghĩa khung của thuật toán (Skeleton of an Algorithm) trong một method, trì hoãn một số bước cho subclass. Nó cho subclass định nghĩa lại (Redefine) một số bước mà không thay đổi cấu trúc thuật toán.
Ví dụ Coffee Shop
Mọi đồ uống nóng theo cùng quy trình: xay hạt → pha → rót vào ly → thêm phụ gia (Condiment). Nhưng mỗi loại đồ uống tùy chỉnh các bước cụ thể — espresso dùng xay mịn và không thêm phụ gia, còn latte dùng xay trung bình và thêm sữa nóng.
Cấu trúc (Structure)
Abstract Class — Khung thuật toán (Algorithm Skeleton)
public abstract class BeverageMaker
{
// Template Method — định nghĩa khung thuật toán
public void Prepare()
{
GrindBeans();
Brew();
PourInCup();
if (CustomerWantsCondiments())
AddCondiments();
Console.WriteLine();
}
protected abstract void GrindBeans();
protected abstract void Brew();
protected abstract void AddCondiments();
protected virtual void PourInCup() =>
Console.WriteLine(" Rót vào ly...");
// Hook — override tùy chọn (có hành vi mặc định)
protected virtual bool CustomerWantsCondiments() => true;
}
Concrete Class — Tùy chỉnh từng bước
public class EspressoMaker : BeverageMaker
{
protected override void GrindBeans() =>
Console.WriteLine(" Xay 18g hạt espresso mịn");
protected override void Brew() =>
Console.WriteLine(" Chiết xuất ở 9 bar trong 25 giây");
protected override void AddCondiments() =>
Console.WriteLine(" Phục vụ nguyên chất — không phụ gia");
protected override bool CustomerWantsCondiments() => false;
}
public class LatteMaker : BeverageMaker
{
protected override void GrindBeans() =>
Console.WriteLine(" Xay 18g hạt espresso trung bình");
protected override void Brew() =>
Console.WriteLine(" Rút double espresso shot");
protected override void AddCondiments() =>
Console.WriteLine(" Thêm sữa nóng (microfoam mịn)");
}
Client
var makers = new BeverageMaker[] { new EspressoMaker(), new LatteMaker() };
foreach (var maker in makers)
{
Console.WriteLine($"Chuẩn bị {maker.GetType().Name.Replace("Maker", "")}:");
maker.Prepare();
}
EspressoMaker override hook CustomerWantsCondiments() trả về false. Thuật toán bỏ qua AddCondiments(). Đây là hook — method có hành vi mặc định mà subclass có thể override tùy chọn.
Các loại method trong Template Method
| Loại | Mục đích | Modifier |
|---|---|---|
| Template Method | Định nghĩa khung thuật toán | public sealed |
| Abstract method | Phải được override bởi subclass | protected abstract |
| Concrete method | Hành vi dùng chung (default implementation) | protected virtual |
| Hook | Override tùy chọn với hành vi mặc định | protected virtual trả bool |
Nguyên tắc Hollywood (Hollywood Principle)
"Don't call us, we'll call you."
Base class gọi method của subclass, không phải ngược lại. Template method kiểm soát luồng — subclass cung cấp chi tiết implementation.
Template Method vs Strategy
| Template Method | Strategy | |
|---|---|---|
| Cơ chế | Inheritance | Composition |
| Khi nào chọn | Cấu trúc thuật toán cố định, bước thay đổi | Toàn bộ thuật toán thay đổi |
| Thay đổi runtime | Không (cố định lúc compile) | Có (inject strategy khác) |
Sử dụng thực tế trong .NET (.NET Real-World Usage)
Stream—Read()/Write()là template method; subclass overrideReadByte()/WriteByte()- ASP.NET Core
ControllerBase— lifecycle method nhưOnActionExecuting() BackgroundService—ExecuteAsync()là template method với khung đã cung cấp- Test fixture —
SetUp()/TearDown()trong unit test framework
Khi nào sử dụng (When to Use)
- Có cấu trúc thuật toán cố định với bước thay đổi
- Hành vi chung giữa subclass nên nằm ở một nơi
- Muốn kiểm soát extension point (Hollywood Principle)
Khi nào KHÔNG sử dụng (When NOT to Use)
- Thuật toán thay đổi hoàn toàn — dùng Strategy
- Ít bước chung — overhead inheritance không đáng
- Cần thay đổi hành vi lúc runtime — Strategy tốt hơn
Điểm chính (Key Takeaways)
- Template Method định nghĩa khung thuật toán trong base class
- Subclass override bước cụ thể mà không thay đổi cấu trúc tổng thể
- Hook cung cấp điểm tùy chỉnh tùy chọn với hành vi mặc định
- Dùng inheritance — nếu prefer composition, dùng Strategy
Câu hỏi phỏng vấn (Interview Questions)
Q: Tại sao đánh dấu template method là sealed?
Để ngăn subclass thay đổi cấu trúc thuật toán. Mục đích là base class kiểm soát luồng. Nếu subclass override được template method itself, guarantee bị mất.
Q: Template Method khác polymorphism thông thường như thế nào? Template Method là cách dùng polymorphism cụ thể. Polymorphism thông thường là subclass override method. Template Method thêm thứ tự gọi cố định — base class gọi nhiều abstract/virtual method theo thứ tự cụ thể. Cấu trúc là đổi mới chính.
Q: "Hook" trong Template Method là gì?
Hook là method có default implementation mà subclass có thể override tùy chọn. Nó không abstract — cung cấp default hợp lý. Ví dụ: CustomerWantsCondiments() mặc định trả true, nhưng EspressoMaker override trả false.
Chủ đề liên quan (Related Topics)
- Strategy — thay thế dựa trên composition
- Builder — tương tự từng bước, nhưng cho construction
- Factory Method — pattern khác cũng dùng inheritance hook