Creational Design Patterns (Mẫu thiết kế khởi tạo)
Các mẫu Creational là gì?
Các mẫu Creational (khởi tạo) trừu tượng hóa quá trình tạo đối tượng (Object Creation). Thay vì rải rác các lệnh gọi new khắp codebase, các mẫu này tập trung hóa cách đối tượng được xây dựng — cho phép bạn kiểm soát cái gì được tạo, khi nào, và bao nhiêu.
Tại sao chúng quan trọng?
| Vấn đề | Mẫu giải quyết |
|---|---|
| Cần chính xác một instance của class (ví dụ: cấu hình, logger) | Singleton |
| Muốn ủy quyền "class nào được khởi tạo" cho subclass | Factory Method |
| Cần tạo các họ đối tượng liên quan (Families of Related Objects) mà không phụ thuộc vào concrete type | Abstract Factory |
| Xây dựng đối tượng phức tạp từng bước với nhiều thành phần tùy chọn | Builder |
| Muốn sao chép (Clone) đối tượng hiện có thay vì tạo mới từ đầu | Prototype |
Miên kiếm (Domain) Coffee Shop
Tất cả ví dụ trong phần này sử dụng miền Coffee Shop (Quán cà phê). Dưới đây là mô hình cốt lõi:
// Base product
public abstract class Coffee
{
public string Name { get; init; } = "";
public double Price { get; init; }
public List<string> Ingredients { get; init; } = new();
public CupSize Size { get; init; } = CupSize.Medium;
public override string ToString() =>
$"{Name} ({Size}) — ${Price:F2} [{string.Join(", ", Ingredients)}]";
}
public enum CupSize { Small, Medium, Large }
// Concrete products
public class Espresso : Coffee
{
public Espresso()
{
Name = "Espresso";
Price = 2.50;
Ingredients = new() { "Espresso Shot" };
}
}
public class Latte : Coffee
{
public Latte()
{
Name = "Latte";
Price = 4.00;
Ingredients = new() { "Espresso Shot", "Steamed Milk" };
}
}
public class Cappuccino : Coffee
{
public Cappuccino()
{
Name = "Cappuccino";
Price = 3.75;
Ingredients = new() { "Espresso Shot", "Steamed Milk", "Foam" };
}
}
So sánh các mẫu (Pattern Comparison)
| Mẫu | Mục đích (Intent) | Khi nào sử dụng |
|---|---|---|
| Singleton | Một instance, truy cập toàn cục (Global Access) | Trạng thái dùng chung (Shared State): cấu hình, logging, connection pool |
| Factory Method | Trì hoãn khởi tạo (Defer Instantiation) cho subclass | Class không thể dự đoán trước đối tượng nào cần tạo |
| Abstract Factory | Các họ sản phẩm liên quan (Families of Related Products) | UI themes, hệ thống đa nhà cung cấp, code đa nền tảng |
| Builder | Xây dựng phức tạp từng bước (Step-by-step Construction) | Đối tượng có nhiều tham số tùy chọn hoặc bước lắp ráp phức tạp |
| Prototype | Sao chép đối tượng hiện có (Clone Existing Objects) | Khởi tạo tốn kém, hoặc template đối tượng được cấu hình lúc runtime |
Những sai lầm phổ biến (Common Pitfalls)
- Thiết kế quá mức (Over-engineering): Đừng bọc mọi lệnh
newtrong factory. Chỉ dùng khi logic khởi tạo phức tạp hoặc cần thay đổi linh hoạt. - Lạm dụng Singleton: Singleton làm việc kiểm thử (Testing) trở nên khó khăn và che giấu các phụ thuộc (Dependencies). Trong ASP.NET Core, ưu tiên dùng DI-managed singleton.
- Dùng Builder cho đối tượng đơn giản: Nếu đối tượng chỉ có 2-3 trường bắt buộc và không có trường tùy chọn, constructor là đủ.
- Prototype và Deep Copy (Sao chép sâu): Sao chép đối tượng lồng nhau (Nested Objects) yêu cầu deep copy — shallow copy dẫn đến lỗi chia sẻ trạng thái có thể thay đổi (Shared Mutable State).
Chủ đề liên quan (Related Topics)
- Nguyên tắc SOLID — các mẫu creational dựa nhiều vào SRP và DIP
- Dependency Injection — DI container thường thay thế factory và singleton viết tay
- Structural Patterns — cách tổ hợp đối tượng sau khi tạo
- Behavioral Patterns — cách các đối tượng đã tạo giao tiếp với nhau