Patterns quản lý việc tạo objects: Factory, Abstract Factory, Builder, Singleton, Prototype. Khi nào dùng pattern nào, và cách .NET DI thay thế một số patterns.
Factory Method
Vấn đề: Client không cần biết (và KHÔNG NÊN biết) concrete class nào được tạo.
csharp// Interface
public interface INotification
{
Task SendAsync(string to, string message);
}
// Implementations
public class EmailNotification : INotification { /* ... */ }
public class SmsNotification : INotification { /* ... */ }
// Factory
public class NotificationFactory
{
public static INotification Create(string type) => type switch
{
"email" => new EmailNotification(),
"sms" => new SmsNotification(),
"push" => new PushNotification(),
_ => throw new ArgumentException($"Unknown type: {type}")
};
}
// .NET DI Alternative: Keyed Services (.NET 8+)
builder.Services.AddKeyedScoped<INotification, EmailNotification>("email");
builder.Services.AddKeyedScoped<INotification, SmsNotification>("sms");
// Inject: [FromKeyedServices("email")] INotification notifier
Dùng khi: Nhiều implementations cho 1 interface, chọn runtime dựa trên config/input.
Dự án: Payment gateways (Stripe, PayPal, Momo), Export engines (PDF, Excel, CSV).
Abstract Factory
csharp// Tạo FAMILY of related objects
public interface ICloudFactory
{
IDatabase CreateDatabase();
IMessageQueue CreateQueue();
IStorage CreateStorage();
}
public class AzureCloudFactory : ICloudFactory
{
public IDatabase CreateDatabase() => new AzureSqlDatabase();
public IMessageQueue CreateQueue() => new AzureServiceBusQueue();
public IStorage CreateStorage() => new AzureBlobStorage();
}
Dùng khi: Tạo nhóm objects liên quan phải tương thích (Azure stack vs AWS stack).
Dự án: Multi-cloud platforms, cross-platform UI (WPF vs MAUI).
Builder
csharp// Xây dựng object PHỨC TẠP theo từng bước
public class EmailBuilder
{
private string _to = "";
private string _subject = "";
private string _body = "";
private List<string> _cc = [];
private bool _isHtml = false;
public EmailBuilder To(string to) { _to = to; return this; }
public EmailBuilder Subject(string s) { _subject = s; return this; }
public EmailBuilder Body(string b) { _body = b; return this; }
public EmailBuilder Cc(params string[] cc) { _cc.AddRange(cc); return this; }
public EmailBuilder AsHtml() { _isHtml = true; return this; }
public Email Build() => new(_to, _subject, _body, _cc, _isHtml);
}
// Usage (fluent)
var email = new EmailBuilder()
.To("user@example.com")
.Subject("Order Confirmed")
.Body("<h1>Thank you!</h1>")
.Cc("admin@example.com")
.AsHtml()
.Build();
// .NET Built-in Builders: WebApplicationBuilder, HostBuilder, HttpRequestMessage, IConfigurationBuilder
Dùng khi: Constructor >4 tham số, nhiều optional params, construction logic phức tạp.
Singleton
csharp// ❌ Manual Singleton (cũ, avoid)
public class Logger
{
private static readonly Lazy<Logger> _instance = new(() => new Logger());
public static Logger Instance => _instance.Value;
private Logger() { }
}
// ✅ .NET DI: Singleton đúng cách
builder.Services.AddSingleton<ILogger, SerilogLogger>();
builder.Services.AddSingleton<ICacheService, MemoryCacheService>();
// DI container quản lý lifetime, thread-safe, testable (mock interface)
Lưu ý: Trong .NET modern, hầu hết Singleton nên được quản lý bởi DI container chứ không tự viết.
Prototype
csharp// Clone object → tránh tạo mới tốn kém
public class ReportTemplate : ICloneable
{
public object Clone() => MemberwiseClone(); // Shallow copy
}
// .NET Alternative: records with `with` expression
public record ReportSettings(string Title, int PageSize, bool IncludeCharts);
var template = new ReportSettings("Monthly", 50, true);
var customized = template with { Title = "Weekly" }; // Clone + modify
Dùng khi: Object tốn kém để tạo (load config, query DB), cần nhiều bản copy khác nhau chút ít.
Decision Matrix
| Pattern | Vấn đề giải quyết | .NET DI thay thế? |
|---|---|---|
| Factory Method | Chọn implementation runtime | ✅ Keyed Services |
| Abstract Factory | Family of related objects | 🔄 Partial (DI + config) |
| Builder | Complex object construction | ❌ Vẫn cần Builder |
| Singleton | 1 instance toàn app | ✅ AddSingleton<> |
| Prototype | Clone object hiệu quả | 🔄 record with {} |