Singleton: chỉ một thể hiện
Đảm bảo một class chỉ có đúng một instance và ai cũng dùng chung nó. Ví dụ: connection pool, logger, config. Nhưng trong JS, module tự bản chất là singleton — đừng viết pattern này cho vui.
// File: config.ts
// Module trong JS đã là singleton: ai import cũng cùng một object
export const config = {
port: Number(process.env.PORT || 3000),
dbUrl: process.env.DATABASE_URL,
jwtSecret: process.env.JWT_SECRET,
};
Factory: để nơi khác quyết định tạo gì
Factory là hàm tạo object mà người gọi không cần biết class cụ thể. Rất hữu ích khi logic tạo phức tạp hoặc loại object phụ thuộc điều kiện.
// File: factory.js
// Factory: dựa vào role để tạo đối tượng có quyền khác nhau
export function createUser(role) {
const base = { id: uuid(), createdAt: new Date() };
if (role === "admin") return { ...base, permissions: ["*"] };
if (role === "recruiter")
return { ...base, permissions: ["jobs.write"] };
return { ...base, permissions: ["jobs.read"] };
}
// Người gọi chỉ cần: createUser(req.body.role)
Observer: thông báo khi có thay đổi
Một đối tượng (subject) giữ danh sách các “người quan sát” và tự gọi họ khi trạng thái thay đổi. Bạn gặp pattern này hàng ngày: addEventListener, subscribe của Redux, hook của webhook.
// File: observer.js
// Publisher giữ danh sách subscriber
class OrderNotifier {
constructor() { this.listeners = new Set(); }
subscribe(fn) { this.listeners.add(fn); }
emit(order) { this.listeners.forEach((fn) => fn(order)); }
}
const notifier = new OrderNotifier();
notifier.subscribe((o) => sendEmail(o));
notifier.subscribe((o) => logActivity(o));
notifier.emit({ id: 1, total: 299000 });
Strategy: đổi hành vi mà không đổi code
Tách một thuật toán thành các “chiến lược” hoán đổi được. Thay vì chồng if/else trong hàm tính phí, mỗi cách tính là một object truyền vào.
// File: strategy.js
// Tránh: if (voucher === "sale") ... else if (voucher === "blackfriday") ...
const discounts = {
none: (p) => p,
sale10: (p) => p * 0.9,
blackFry: (p) => (p > 100000 ? p - 50000 : p * 0.85),
};
// Chọn strategy bằng một dòng, thêm loại mới không đụng code cũ
const finalPrice = discounts[order.voucher](order.subtotal);
Đừng “nhét” pattern vào code để nghe cho ngầu. Chỉ dùng khi bạn đang gặp đúng bài toán pattern đó giải quyết. Code đơn giản thẳng thắn luôn thắng code “đầy đủ pattern”.
❓ Hệ thống cần thông báo cho email, webhook và log khi một order được tạo. Pattern phù hợp nhất?
- Biết module JS là singleton sẵn
- Dùng Factory khi logic tạo phức tạp
- Nhận diện Observer trong addEventListener
- Thay if/else bằng Strategy khi danh sách dài