Singleton Pattern
Đảm bảo chỉ có 1 instance dùng chung toàn hệ thống
Use case
-
Config service
-
Logger
-
Cache manager
-
Connection pool
-
Tiết kiệm resource
-
Truy cập global dễ dàng
-
Đảm bảo consistency (1 nguồn dữ liệu)
-
Global state → khó test
-
Tight coupling
-
Khó mở rộng (vi phạm SOLID)
-
Khi dùng framework có DI (Laravel, Spring)
-
Khi object có state thay đổi
-
Khi cần test isolation
-
Dễ dùng nhưng đánh đổi testability & flexibility
Factory Pattern
Factory Method là pattern giúp tạo object mà không cần chỉ định class cụ thể.
Use case
-
Payment (VNPay, Momo)
-
Notification (Email, SMS)
-
DB driver / storage
-
Giảm coupling giữa client và class cụ thể
-
Dễ mở rộng (Open/Closed Principle)
-
Tách logic khởi tạo khỏi business
-
Tăng số class / abstraction
-
Có thể dư thừa nếu object đơn giản
-
Factory phình to nếu quá nhiều type
-
Có nhiều implementation cùng interface
-
Logic khởi tạo phức tạp
-
Object đơn giản (chỉ new là xong)
-
Không có nhiều variation
-
Clean architecture vs complexity tăng
“Factory thường đi chung với Strategy để chọn logic runtime”
Strategy pattern
Strategy thay thế if-else bằng cách tách logic thành nhiều class
Use case
-
Payment method
-
Pricing / discount
-
Shipping calculation
-
Sorting / filtering
-
Dễ mở rộng (thêm strategy mới không sửa code cũ)
-
Clean code (loại bỏ if-else)
-
Tuân thủ Open/Closed Principle
-
Nhiều class → khó quản lý
-
Client cần biết chọn strategy nào
-
Overkill nếu logic đơn giản
-
Nhiều logic thay đổi runtime
-
Business rule thay đổi thường xuyên
-
Chỉ có 1–2 case đơn giản
-
Logic không thay đổi
-
Flexibility cao ↔ tăng số lượng class
Observer pattern
Observer giúp 1 event trigger nhiều hành động mà không bị coupling
Use case
-
Order created → email, log, analytics
-
Notification system
-
Event-driven architecture
-
Loose coupling
-
Dễ mở rộng (thêm observer không sửa code cũ)
-
Phù hợp event-driven system
-
Khó debug / trace flow
-
Có thể gây event chain phức tạp
-
Không kiểm soát thứ tự execution
-
1 action → nhiều side-effect
-
Hệ thống cần mở rộng
-
Logic đơn giản
-
Không cần mở rộng
-
Scalability cao ↔ khó trace & debug