Abstract Factory: họ nguyên liệu và vùng miền
Ôn lại trước khi học
Giới thiệu
Bài này học Abstract Factory tạo cả họ đối tượng. Bạn dùng nó để pizza đúng vị từng vùng.
Kiến thức cần nhớ
Định nghĩa
- Cung cấp giao diện tạo họ đối tượng liên quan.
- Không cần chỉ rõ lớp cụ thể đằng sau.
- Từ khóa là họ liên quan và giấu cụ thể.
- Ví dụ đời thường: như bếp chỉ gọi lấy bột, xưởng tự giao đúng loại vùng.
Xưởng nguyên liệu theo vùng
- Pizza New York: bột mỏng, sốt marinara, phô mai tươi.
- Pizza Chicago: bột dày, sốt cà chua nghiền, phô mai sợi.
- Mỗi pizza chỉ giữ 1 xưởng chung, cần gì hỏi xưởng.
- Nếu pizza tự đi chợ sẽ dễ mua nhầm vùng.
Nhất quán trong họ
- Bột sốt phô mai cùng 1 pizza phải cùng vùng mới chuẩn vị.
- Vì cả 3 ra từ cùng 1 xưởng nên nhất quán tự đảm bảo.
- Không cần lập trình viên nhớ bằng kỷ luật.
- Rẽ nhánh thủ công không bao giờ đảm bảo được điều này.
| Khía cạnh | Factory Method | Abstract Factory |
|---|---|---|
| Tạo ra | 1 product | Cả họ product |
| Ai quyết định | Lớp con creator | Xưởng từng họ |
| Nhất quán họ | Không đặt ra | Đảm bảo bởi cấu trúc |
Ví dụ
- Input: chuẩn bị pizza phô mai New York. Output: bột sốt phô mai đều bản New York.
- Giải thích: cùng 1 xưởng nên không lẫn món Chicago.
- Input: thêm xưởng California. Output: pizza mới dùng bộ mới, 2 vùng cũ nguyên vẹn.
- Giải thích: thêm họ mới không chạm code cũ.
💻 Bài tập
Ngôn ngữ: C++17 (hoặc Java). Nộp vào day-074/.
Bài 1: Xưởng nguyên liệu theo vùng
struct Dough { virtual std::string name() const = 0; virtual ~Dough() = default; };
struct Sauce { ... }; struct Cheese { ... }; struct Clams { ... };
struct PizzaIngredientFactory {
virtual std::unique_ptr<Dough> createDough() = 0;
virtual std::unique_ptr<Sauce> createSauce() = 0;
virtual std::unique_ptr<Cheese> createCheese() = 0;
virtual std::unique_ptr<Clams> createClams() = 0;
virtual ~PizzaIngredientFactory() = default;
};
| Xưởng | Dough | Sauce | Cheese | Clams |
|---|---|---|---|---|
NYPizzaIngredientFactory | ThinCrustDough | MarinaraSauce | ReggianoCheese | FreshClams |
ChicagoPizzaIngredientFactory | ThickCrustDough | PlumTomatoSauce | MozzarellaCheese | FrozenClams |
CheesePizza và ClamPizza nhận PizzaIngredientFactory&. prepare() hỏi xưởng lấy nguyên liệu. Hai lớp pizza không biết vùng nào.
NYPizzaStore.order("cheese") -> nguyên liệu [Thin Crust, Marinara, Reggiano]
ChicagoPizzaStore.order("clam") -> [Thick Crust, Plum Tomato, Mozzarella, Frozen Clams]
Viết test kiểm tra mọi nguyên liệu trong 1 pizza cùng vùng.
Bài 2: Thêm vùng California
Thêm CaliforniaPizzaIngredientFactory (CauliflowerDough, PestoSauce, GoatCheese, FreshClams) và CaliforniaPizzaStore. Không file cũ nào đổi.
Sau đó thêm nguyên liệu mới Veggies vào mọi xưởng. Đếm số file phải sửa. Ghi vào README.md: đây là điểm yếu của Abstract Factory.
Bài 3: Giao diện đa nền tảng (nâng cao)
Mô phỏng bộ widget: Button, Checkbox, TextField. Hai họ: LightTheme và DarkTheme. Mỗi widget có std::string render() trả chuỗi mô tả màu nền, màu chữ.
WidgetFactoryvới 2 cài đặt.LoginFormnhậnWidgetFactory&, dựng form 2 ô nhập, 1 checkbox, 1 nút.- Chọn xưởng từ biến môi trường
THEME. Viết test chứng minh không có widget sáng nào lọt vào form tối.
✅ Tiêu chí hoàn thành
- Test nhất quán nguyên liệu theo vùng pass.
- Thêm California không sửa file cũ.
- Có số file phải sửa khi thêm
Veggieskèm nhận xét. - Vẽ sơ đồ lớp: xưởng trừu tượng, 2 xưởng cụ thể, 2 họ sản phẩm.
❓ Câu hỏi ôn tập
- Abstract Factory tạo ra cái gì?
- Xưởng vùng giúp pizza nhất quán thế nào?
- Thêm họ mới và thêm món mới cái nào dễ?
- Khác Factory Method ở điểm nào?
🌕 Bạn đã hoàn thành ngày 74. Làm hết bài tập phía trên rồi sang ngày tiếp theo.