Chuyển tới nội dung chính

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 subclassFactory 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 typeAbstract 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ọnBuilder
Muốn sao chép (Clone) đối tượng hiện có thay vì tạo mới từ đầuPrototype

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ẫuMục đích (Intent)Khi nào sử dụng
SingletonMộ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 MethodTrì hoãn khởi tạo (Defer Instantiation) cho subclassClass không thể dự đoán trước đối tượng nào cần tạo
Abstract FactoryCá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
BuilderXâ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
PrototypeSao 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 new trong 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).