Simple Factory: đóng gói khởi tạo đối tượng pizza

Vì sao từ khóa tạo mới gây cứng nhắc, cách gom khởi tạo vào một xưởng đơn giản qua câu chuyện Pizza Store.
Trung bìnhDesign pattern ~60 phút

Giới thiệu

Bài này học cách gom chỗ tạo đối tượng. Bạn không rải lệnh tạo khắp nơi nữa.

Kiến thức cần nhớ

Rải lệnh tạo gây cứng

  • Mỗi nhánh gọi thẳng 1 lớp pizza cụ thể.
  • Thêm loại mới phải mở cửa hàng ra sửa.
  • Đổi tên lớp cũng phải sửa cửa hàng.
  • Ví dụ đời thường: mỗi chi nhánh tự nặn công thức.

Xưởng đơn giản gom lại

  • Mọi cách tạo dồn vào 1 xưởng chung.
  • Cửa hàng hỏi xưởng, nhận pizza chung.
  • Cửa hàng chạy 4 bước chuẩn không cần biết loại.
  • Ví dụ đời thường: kho tổng phát hàng cho chi nhánh.

Giới hạn của xưởng đơn

  • Thêm chiều vùng miền thì xưởng phình to.
  • Pizza cùng tên mà New York khác Chicago.
  • Lúc đó cần Factory Method bài sau.
  • Ví dụ đời thường: 1 kho không cân 2 miền vị khác.
Tiêu chíRải khắp nơiQua xưởng
Biết lớp cụ thểRải trong cửa hàngGom trong xưởng
Thêm loại mớiMở cửa hàng sửaSửa đúng xưởng
Dùng lạiSao chép khối lệnhDùng chung xưởng

Ví dụ

  • Input: khách gọi pizza phô mai. Output: xưởng trả đúng loại, cửa hàng chạy đủ 4 bước.
  • Giải thích: kiến thức lớp cụ thể nằm 1 chỗ duy nhất.

💻 Bài tập

Ngôn ngữ: C++17 (hoặc Java). Nộp vào day-018/.

Bài 1: Pizza Store với Simple Factory

class Pizza {
 public:
  virtual std::string name() const = 0;
  virtual void prepare(); virtual void bake(); virtual void cut(); virtual void box();
  const std::vector<std::string> &log() const;   // ghi lại các bước để test
  virtual ~Pizza() = default;
};
class SimplePizzaFactory { public: std::unique_ptr<Pizza> create(const std::string &type) const; };
class PizzaStore {
 public:
  explicit PizzaStore(const SimplePizzaFactory &f);
  std::unique_ptr<Pizza> order(const std::string &type);  // create + 4 bước
};
Loạiname()
"cheese""Pizza phô mai"
"pepperoni""Pizza xúc xích"
"veggie""Pizza rau"
"clam""Pizza nghêu"

Ràng buộc

  • PizzaStore không #include lớp pizza cụ thể nào.
  • Loại không tồn tại: create trả nullptr, order ném std::invalid_argument.
order("cheese")  -> name "Pizza phô mai", log = [prepare, bake, cut, box]
order("sushi")   -> ném invalid_argument

Bài 2: Thêm loại mới

  1. Thêm "seafood" và chứng minh chỉ SimplePizzaFactory và file lớp mới thay đổi.
  2. Đổi create sang bảng đăng ký: std::unordered_map<std::string, std::function<std::unique_ptr<Pizza>()>>. Thêm hàm registerType(name, creator). Thêm loại mới lúc chạy mà không sửa factory.

Bài 3: Xưởng tài liệu (nâng cao)

DocumentFactory::create(path) chọn lớp theo đuôi file: .txt ra TextDocument, .csv ra SpreadsheetDocument, .md ra MarkdownDocument. Mỗi lớp có std::string summary().

  • TextDocument: số dòng, số từ.
  • SpreadsheetDocument: số hàng, số cột.
  • MarkdownDocument: số heading #.

Đuôi không hỗ trợ thì trả lỗi rõ ràng. Viết main nhận danh sách file từ dòng lệnh và in summary() từng file.

✅ Tiêu chí hoàn thành

  • Test mẫu pass.
  • PizzaStore không phụ thuộc lớp cụ thể (kiểm tra bằng #include).
  • Bảng đăng ký cho phép thêm loại lúc chạy.
  • Giải thích được giới hạn của Simple Factory khi có thêm chiều vùng miền.

❓ Câu hỏi ôn tập

  • Vì sao rải lệnh tạo khắp nơi lại xấu?
  • Xưởng đơn giản làm gì?
  • Quy trình pizza gồm 4 bước nào?
  • Khi nào xưởng đơn không đủ?

🌕 Bạn đã hoàn thành ngày 18. Làm hết bài tập phía trên rồi sang ngày tiếp theo.

Bớt paste mù, hiểu sâu từng dòng mình viết.

180 Days Challenge. 180 ngày cai nghiện vibe code.