So sánh 3 factory và nghịch lý mở rộng

Đặt Simple Factory, Factory Method và Abstract Factory cạnh nhau, chốt nghịch lý thêm họ dễ thêm món khó và cẩm nang chọn.
KhóDesign pattern ~60 phút

Giới thiệu

Bài này học cách chọn giữa 3 loại factory. Bạn dùng nó để không thiết kế thừa cho bài toán nhỏ.

Kiến thức cần nhớ

Hành trình Pizza Store

  • Nấc 1: rẽ nhánh tạo pizza trong thân cửa hàng.
  • Nấc 2: gom vào xưởng đơn giản, cửa hàng sạch nhưng xưởng phình.
  • Nấc 3: mỗi chi nhánh tự tạo pizza vùng mình theo khung chung.
  • Nấc 4: gom nguyên liệu thành xưởng theo họ cho nhất quán.
  • Ví dụ đời thường: như quán nhỏ 1 bếp, lớn dần mới cần nhiều bếp chuyên.

Bảng so sánh

  • Xưởng đơn giản: 1 món theo tên gọi, xưởng trung tâm quyết.
  • Factory Method: 1 product, lớp con quyết định.
  • Abstract Factory: cả họ product, xưởng từng họ quyết.
Tiêu chíĐơn giảnMethodAbstract
Tạo ra1 món1 productCả họ
Thêm họ mớiSửa xưởngThêm lớp mớiThêm xưởng mới
Thêm món mớiSửa 1 chỗThêm từng vùngSửa mọi xưởng

Nghịch lý mở rộng

  • Mọi thiết kế dễ theo 1 chiều và khó theo chiều còn lại.
  • Thêm họ mới thì Method và Abstract dễ, code cũ nguyên vẹn.
  • Thêm món mới vào Abstract rất đau vì sửa mọi xưởng.
  • Phải cược vào chiều nào hay đổi hơn theo lịch sử dự án.

Cây quyết định

  • Không có họ biến thể thì tạo trực tiếp cho gọn.
  • Logic tạo lặp nhiều nơi thì xưởng đơn giản là đủ.
  • Có khung chung mà khâu tạo đổi theo biến thể thì Method.
  • Sản phẩm phải đi cùng họ nhất quán thì Abstract.

Ví dụ

  • Input: thêm vùng mới vào hệ Factory Method. Output: khung cũ nguyên vẹn, vùng mới chạy đúng quy trình.
  • Giải thích: thêm creator mới không chạm khung.
  • Input: thêm món mới vào hệ Abstract Factory. Output: phải sửa giao diện và mọi xưởng.
  • Giải thích: không có cách thêm mà không chạm code cũ.

💻 Bài tập

Ngôn ngữ: C++17 (hoặc Java). Nộp vào day-075/. Bài này là so sánh có code minh họa.

Bài 1: Bốn nấc tiến hóa

Viết 4 thư mục step1/ tới step4/, cùng làm 1 việc: cửa hàng bán pizza cheese và clam cho 2 vùng NY và Chicago.

Thư mụcCách tạo đối tượng
step1/if/else lồng nhau theo vùng và loại, ngay trong orderPizza
step2/Simple Factory nhận (vùng, loại)
step3/Factory Method: mỗi chi nhánh ghi đè createPizza
step4/Factory Method + Abstract Factory nguyên liệu

Mỗi bước có cùng 1 file test order_test.cpp và cho cùng output.

Bài 2: Đo chi phí thay đổi

Áp 3 thay đổi lên cả 4 bước. Mỗi thay đổi đếm số file và số dòng bị sửa bằng git diff --stat:

  1. Thêm loại pizza veggie.
  2. Thêm vùng California.
  3. Thêm nguyên liệu mới Pepperoni cho mọi vùng.
thay_đổi         step1        step2        step3        step4
thêm veggie      ... files    ...
thêm California  ...
thêm Pepperoni   ...

Viết 5 câu kết luận: mỗi pattern dễ theo chiều nào, khó theo chiều nào.

Bài 3: Chọn pattern cho tình huống (nâng cao)

Với mỗi tình huống, chọn: tạo trực tiếp, Simple Factory, Factory Method, Abstract Factory. Viết 2 câu lý do và phác thảo interface (5-10 dòng code):

  1. Ứng dụng đọc ảnh PNG, JPEG, WebP theo đuôi file.
  2. Thư viện kiểm thử cho phép người dùng tự định nghĩa cách tạo test fixture.
  3. Game có 3 chủng tộc, mỗi chủng tộc có lính, nhà, vũ khí riêng phải đi cùng nhau.
  4. Tạo std::vector<int> rỗng.
  5. Driver cơ sở dữ liệu: MySQL, Postgres, SQLite, mỗi loại có Connection, Statement, ResultSet.

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

  • 4 bước cùng pass 1 file test.
  • Bảng đo chi phí thay đổi có số thật từ git diff --stat.
  • Bài 3 có lựa chọn và interface cho cả 5 tình huống.
  • Phân biệt được 3 loại factory bằng 1 câu mỗi loại.

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

  • Ba factory khác nhau ở đối tượng tạo ra là gì?
  • Nghịch lý mở rộng nghĩa là gì?
  • Khi nào xưởng đơn giản là đủ?
  • Dấu hiệu nào báo cần nâng lên Method hay Abstract?

🌕 Bạn đã hoàn thành ngày 75. 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.