Factory Method: framework và creator song song product
Định nghĩa Factory Method, khung cửa hàng nhượng quyền, và cấu trúc creator song song product qua New York và Chicago.
Trung bìnhDesign pattern ~60 phút
Ôn lại trước khi học
Giới thiệu
Bài này học cách nhượng quyền pizza 2 miền. Bạn để chi nhánh tự quyết khâu tạo.
Kiến thức cần nhớ
Vấn đề nhượng quyền
- Quy trình chung nhưng vị mỗi vùng khác nhau.
- Phô mai New York vỏ mỏng, Chicago vỏ dày.
- 1 xưởng trung tâm không cân 2 chiều loại và vùng.
- Ví dụ đời thường: cùng phở mà Bắc Nam khác vị.
Hai hệ song song
- Một bên là khung cửa hàng giữ quy trình chung.
- Một bên là họ pizza từng vùng.
- Khâu tạo để trống, chi nhánh tự điền.
- Ví dụ đời thường: công thức chung, bếp vùng tự nấu.
Thêm vùng mới không sửa cũ
- Thêm California chỉ thêm chi nhánh và pizza mới.
- Khung cũ và 2 vùng cũ nguyên vẹn.
- Mỗi chi nhánh gắn với cụm pizza của mình.
- Ví dụ đời thường: mở chi nhánh mới không sửa trụ sở.
| Tiêu chí | Xưởng đơn | Factory Method |
|---|---|---|
| Ai quyết tạo | 1 xưởng giữa | Mỗi chi nhánh tự quyết |
| Thêm vùng mới | Mở xưởng sửa | Thêm nhánh mới |
| Quy trình chung | Không có | Có ở khung |
Ví dụ
- Input: gọi phô mai ở New York và Chicago. Output: 2 chiếc khác vị đúng vùng.
- Giải thích: cùng khung chạy nhưng khâu tạo khác nhau.
💻 Bài tập
Ngôn ngữ: C++17 (hoặc Java). Nộp vào day-025/.
Bài 1: Factory Method cho chuỗi pizza
class PizzaStore {
public:
std::unique_ptr<Pizza> orderPizza(const std::string &type); // không virtual: quy trình chung
virtual ~PizzaStore() = default;
protected:
virtual std::unique_ptr<Pizza> createPizza(const std::string &type) = 0; // factory method
};
| Chi nhánh | createPizza("cheese") trả | name() | cut() |
|---|---|---|---|
NYPizzaStore | NYStyleCheesePizza | "NY phô mai vỏ mỏng" | cắt chéo |
ChicagoPizzaStore | ChicagoStyleCheesePizza | "Chicago phô mai vỏ dày" | cắt ô vuông |
Mỗi chi nhánh có 2 loại: "cheese" và "veggie". orderPizza gọi createPizza rồi prepare, bake, cut, box. Ghi các bước vào log để test.
NYPizzaStore.orderPizza("cheese") -> "NY phô mai vỏ mỏng", log có "cắt chéo"
ChicagoPizzaStore.orderPizza("cheese") -> "Chicago phô mai vỏ dày", log có "cắt ô vuông"
orderPizza("unknown") -> ném invalid_argument
Bài 2: Thêm vùng California
Thêm CaliforniaPizzaStore với 2 loại pizza mới. Chứng minh bằng git diff --stat: không file cũ nào đổi.
Viết thêm 3 câu: vì sao orderPizza không nên virtual, và điều gì xảy ra nếu chi nhánh ghi đè nó.
Bài 3: Factory Method ngoài pizza (nâng cao)
Viết khung xuất báo cáo:
class ReportExporter {
public:
std::string exportReport(const std::vector<Row> &rows); // header + từng dòng + footer
protected:
virtual std::unique_ptr<Formatter> createFormatter() = 0;
};
Viết CsvExporter, JsonExporter, MarkdownExporter. Mỗi exporter tạo Formatter riêng với header(), row(const Row&), footer().
rows = [{name: "An", score: 9}, {name: "Bình", score: 7}]
CsvExporter -> "name,score\nAn,9\nBình,7\n"
MarkdownExporter -> "| name | score |\n| --- | --- |\n| An | 9 |\n| Bình | 7 |\n"
JsonExporter -> "[{\"name\":\"An\",\"score\":9},{\"name\":\"Bình\",\"score\":7}]"
✅ Tiêu chí hoàn thành
- Test mẫu pass.
-
PizzaStorevàReportExporterkhông biết lớp sản phẩm cụ thể nào. - Thêm California chỉ thêm file mới.
- Vẽ sơ đồ 2 hệ song song Creator và Product.
❓ Câu hỏi ôn tập
- Factory Method là gì, nói 1 câu?
- Khung giữ gì, chi nhánh giữ gì?
- Vì sao thêm vùng không sửa khung?
- Khác xưởng đơn ở đâu?
🌕 Bạn đã hoàn thành ngày 25. Làm hết bài tập phía trên rồi sang ngày tiếp theo.