Menu
CoddyTech

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ở PDF

Mẫ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.

challenge icon

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ện INotification trong không gian tên Notifications vớ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ớp NotificationFactory trong cùng không gian tên, với phương thức Create(string type) trả về INotification phù hợp dựa trên chuỗi type:
    • "email" trả về một đối tượng EmailNotification
    • "sms" trả về một đối tượng SmsNotification
    • "push" trả về một đối tượng PushNotification
    Với mọi type không được nhận diện, hãy trả về một đối tượng EmailNotification là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 minutes

Lư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ả
    }
}
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch C# online