Menu
CoddyTech

Mẫu Factory

Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 91 trên 110.

Mẫu Factory giao việc tạo đối tượng cho một phương thức hoặc lớp riêng, giúp bạn tạo đối tượng mà không cần chỉ định chính xác lớp của chúng. Điều này khác với hàm khởi tạo factory bạn đã học trước đó: mẫu Factory là một cách tiếp cận thiết kế, trong đó logic tạo đối tượng được tập trung và có thể trả về các kiểu khác nhau tùy theo đầu vào.

Hãy xét tình huống bạn cần tạo nhiều loại thông báo khác nhau. Thay vì để máy khách quyết định sẽ khởi tạo lớp (class) nào, một factory sẽ xử lý quyết định đó:

abstract class Notification {
  void send(String message);
}

class EmailNotification implements Notification {
  @override
  void send(String message) => print('Email: $message');
}

class SMSNotification implements Notification {
  @override
  void send(String message) => print('SMS: $message');
}

class NotificationFactory {
  static Notification create(String type) {
    switch (type) {
      case 'email':
        return EmailNotification();
      case 'sms':
        return SMSNotification();
      default:
        return EmailNotification();
    }
  }
}

void main() {
  var notification = NotificationFactory.create('sms');
  notification.send('Hello!');  // SMS: Hello!
}

Code phía client không cần biết về EmailNotification hay SMSNotification, mà chỉ yêu cầu factory tạo thông báo thuộc một loại nhất định. Nhờ vậy, bạn dễ dàng thêm loại thông báo mới: chỉ cần sửa factory, không phải sửa mọi nơi tạo thông báo.

Hãy dùng mẫu Factory khi việc tạo đối tượng cần logic phức tạp, khi bạn muốn ẩn các lớp triển khai với bên gọi, hoặc khi kiểu đối tượng cần tạo phụ thuộc vào điều kiện lúc chạy.

challenge icon

Thử thách

Dễ

Hãy tạo một trình tạo tài liệu bằng mẫu Factory! Bạn sẽ tạo một hệ thống tạo ra nhiều loại tài liệu khác nhau (báo cáo, hóa đơn và thư) thông qua một factory tập trung, để code phía client không cần biết các lớp tài liệu cụ thể.

Bạn sẽ sắp xếp code thành hai tệp:

  • document_factory.dart: Tạo hệ thống tài liệu tại đây:
    • Một lớp trừu tượng Document có phương thức generate(String content) trả về một String
    • Ba lớp cụ thể triển khai Document:
      • Report - phương thức generate trả về === REPORT ===\n[content]\n=============
      • Invoice - phương thức generate trả về INVOICE\n--------\n[content]\nTotal Due
      • Letter - phương thức generate trả về Dear Reader,\n[content]\nSincerely
    • Một lớp DocumentFactory có phương thức tĩnh create(String type) trả về Document phù hợp dựa trên chuỗi kiểu: "report", "invoice" hoặc "letter". Với mọi kiểu không xác định, hãy trả về Letter làm mặc định
  • main.dart: Nhập factory tài liệu và minh họa cách factory tạo các loại tài liệu khác nhau mà client không cần biết các lớp cụ thể:
    • Dùng factory để tạo báo cáo và in ra kết quả tạo báo cáo đó với nội dung Sales increased by 25%
    • In ra một dòng trống
    • Dùng factory để tạo hóa đơn và in ra kết quả tạo hóa đơn đó với nội dung Widget x3 - $150
    • In ra một dòng trống
    • Dùng factory để tạo thư và in ra kết quả tạo thư đó với nội dung Thank you for your order

Hãy để ý rằng tệp chính chỉ tương tác với factory và kiểu trừu tượng Document, nó không bao giờ trực tiếp tạo các đối tượng Report, Invoice hoặc Letter!

Đầu ra dự kiến:

=== REPORT ===
Sales increased by 25%
=============

INVOICE
--------
Widget x3 - $150
Total Due

Dear Reader,
Thank you for your order
Sincerely

Tự làm thử

import 'document_factory.dart';

void main() {
  // TODO: Dùng DocumentFactory.create() để tạo báo cáo
  // Sau đó in ra kết quả tạo báo cáo với nội dung: "Sales increased by 25%"
  
  // TODO: In ra một dòng trống
  
  // TODO: Dùng DocumentFactory.create() để tạo hóa đơn
  // Sau đó in ra kết quả tạo hóa đơn với nội dung: "Widget x3 - \$150"
  
  // TODO: In ra một dòng trống
  
  // TODO: Dùng DocumentFactory.create() để tạo thư
  // Sau đó in ra kết quả tạo báo cáo với nội dung: "Thank you for your order"
}
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 Dart online