Mẫu Factory
Thuộc phần Lập trình hướng đối tượng trong hành trình C# của Coddy. Bài học 53 trên 70.
Mẫu Factory là mẫu khởi tạo giao việc tạo đối tượng cho một phương thức hoặc lớp riêng. Thay vì dùng trực tiếp new trong code, bạn yêu cầu một factory tạo đối tượng giúp bạn. Cách này tập trung logic khởi tạo và giúp code linh hoạt hơn.
Hãy xem xét tình huống bạn cần tạo nhiều loại tài liệu khác nhau. Nếu không có factory, code của bạn sẽ bị gắn chặt với các lớp cụ thể:
// Không dùng Factory: logic khởi tạo nằm rải rác
IDocument doc;
if (type == "pdf")
doc = new PdfDocument();
else if (type == "word")
doc = new WordDocument();Factory gom logic ra quyết định này vào một nơi:
public interface IDocument
{
void Open();
}
public class PdfDocument : IDocument
{
public void Open() => Console.WriteLine("Opening PDF");
}
public class WordDocument : IDocument
{
public void Open() => Console.WriteLine("Opening Word");
}
public class DocumentFactory
{
public IDocument Create(string type)
{
switch (type)
{
case "pdf":
return new PdfDocument();
case "word":
return new WordDocument();
default:
throw new ArgumentException("Unknown type");
}
}
}Giờ đây, code phía máy khách chỉ cần yêu cầu những gì nó cần mà không cần biết các lớp cụ thể:
var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open(); // Đang mở PDFMẫu Factory phát huy hiệu quả khi sau này bạn cần thêm các kiểu mới. Để thêm SpreadsheetDocument, bạn chỉ cần thay đổi factory, không cần sửa ở mọi nơi tạo tài liệu. Sự tách biệt này giúp bạn dễ bảo trì và kiểm thử code hơn.
Thử thách
DễHãy xây dựng một hệ thống thông báo bằng mẫu thiết kế Factory (Factory pattern). Thay vì tạo trực tiếp các loại thông báo khác nhau ở nhiều nơi trong đoạn code, bạn sẽ tập trung logic tạo thông báo vào một lớp factory. Lớp này quyết định cần tạo thông báo nào dựa trên một chuỗi (string) định danh đơn giản.
Bạn sẽ tổ chức đoạn code trong ba tệp:
Notification.cs: Định nghĩa giao diệnINotificationtrong không gian tênNotificationsvới một phương thức duy nhất làSend(string message), trả về một chuỗi. Sau đó, tạo ba lớp triển khai giao diện này:EmailNotification: trả về"Email: {message}"SmsNotification: trả về"SMS: {message}"PushNotification: trả về"Push: {message}"
NotificationFactory.cs: Tạo lớpNotificationFactorytrong cùng không gian tên, với phương thứcCreate(string type)trả vềINotificationphù hợp dựa trên chuỗi type:"email"trả về một đối tượngEmailNotification"sms"trả về một đối tượngSmsNotification"push"trả về một đối tượngPushNotification
EmailNotificationlàm mặc định.Program.cs: Kết hợp mọi thứ bằng cách tạo một instance của factory rồi dùng nó để tạo thông báo dựa trên đầu vào. Factory xử lý toàn bộ việc quyết định cần khởi tạo lớp cụ thể nào.
Bạn sẽ nhận hai đầu vào:
- Loại thông báo (ví dụ:
sms) - Nội dung cần gửi (ví dụ:
Your order has shipped)
Dùng factory để tạo loại thông báo phù hợp, sau đó gọi phương thức Send với nội dung và in kết quả ra.
Ví dụ, nếu đầu vào là push và Meeting in 5 minutes, đầu ra sẽ là:
Push: Meeting in 5 minutesLưu ý rằng đoạn code chính của bạn không bao giờ dùng new EmailNotification() hay cách tương tự, mà chỉ yêu cầu factory tạo đối tượng cần thiết. Nếu sau này bạn thêm SlackNotification, bạn chỉ cần cập nhật factory, không phải sửa mọi nơi tạo thông báo!
Tự làm thử
using System;
using Notifications;
class Program
{
public static void Main(string[] args)
{
// Đọc đầu vào
string type = Console.ReadLine();
string message = Console.ReadLine();
// TODO: Tạo một instance của NotificationFactory
// TODO: Dùng factory để tạo thông báo phù hợp
// TODO: Gọi phương thức Send và in ra kết quả
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Các khái niệm cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiKhông gian tên và chỉ thịGiới thiệu về lớp và đối tượngTừ khóa thisPhương thức và tham sốTrường và thuộc tínhHàm khởi tạoKhởi tạo đối tượngÔn tập: Máy tính đơn giản4Kế thừa
Cú pháp kế thừa cơ bản (:)Từ khóa 'base'Từ khóa virtual và overrideLớp sealedLớp cơ sở 'object'Ôn tập: hệ phân cấp nhân viên7Tính năng nâng cao
Nạp chồng toán tửBộ lập chỉ mục (this[])Ghi đè ToString()Phương thức mở rộngÔn tập: Danh sách tùy chỉnh10Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếSingleton an toàn với luồngMẫu FactoryMẫu Observer (sự kiện)Mẫu Strategy2Thuộc tính và thành viên tĩnh
Thuộc tính tự độngThuộc tính chỉ đọc hoặc chỉ ghiTrường và phương thức tĩnhLớp tĩnhThành viên có thân biểu thức5Đa hình và interface
Đa hình lúc biên dịch và lúc chạyInterface và lớp trừu tượngNhiều interfaceInterface tường minhUpcasting và downcastingÔn tập: bộ tính toán hình học8Các khái niệm OOP nâng cao
Ưu tiên composition hơn kế thừaGenerics (lớp và phương thức)Delegate và sự kiệnAttribute và reflectionGiao diện IDisposable và câu lệnh usingKiến thức cơ bản về dependency injection11Các mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổ hợpTự luyện tập: Trình biên dịch C# online