Policy-Based Design
Policy-Based Design (Thiết kế dựa trên chính sách) là một kỹ thuật cực kỳ mạnh mẽ trong C++, được phổ biến bởi Andrei Alexandrescu trong cuốn sách nổi tiếng Modern C++ Design.
Ta có thể hiểu nó như một trò chơi xếp hình Lego. Thay vì đúc nguyên 1 khối ngay từ đầu, ta tạo ra một bộ khung và cho phép người dùng lắp ghép những tính năng mong muốn vào bộ khung đó ngay khi biên dịch
Vấn đề kỹ thuật: Bài toán in nhật ký logger Giả sử ta cần viết một class Logger để in thông báo ra màn hình. Tuy nhiên, gặp phải hai yêu cầu trái ngược nhau:
-
- Chạy đa luồng (Multi-thread): Cần có cơ chế khóa (Mutex) để các luồng không tranh giành nhau, gây lộn xộn dòng in.
-
- Chạy đơn luồng (Single-thread): Không cần khóa, vì nếu dùng khóa sẽ làm chậm chương trình một cách vô ích.
Nếu ta dùng if-else tại Run time: ta sẽ thêm một biến is_multithread và kiểm tra nó mỗi khi in:
void log(string msg) {
if (is_multithread) {
mutex.lock();
}
cout << msg << endl;
if (is_multithread) {
mutex.unlock();
}
}
=> Cứ mỗi dòng log được in ra, CPU lại phải tốn công kiểm tra if (is_multithread). Nếu in hàng triệu dòng, việc kiểm tra này gây lãng phí hiệu năng.
2. Giải pháp từ Policy-Based Design (Quyết định khi biên dịch)
Thay vì kiểm tra lúc chương trình đang chạy, chúng ta bắt C++ quyết định luôn từ lúc biên dịch (Compile-time) bằng cách tách khả năng "Khóa" thành các Chính sách (Policies) riêng biệt.
Bước 1: Định nghĩa các policy Tạo ra 2 class có cấu trúc giống nhau nhưng bên trong thực thi khác nhau
#include <iostream>
#include <mutex>
// 1. Chính sách dành cho đa luồng: Dùng khóa thật
struct MultiThreadPolicy {
using mutex_t = std::mutex; // Định nghĩa mutex_t là khóa thật
};
// 2. Chính sách dành cho đơn luồng: Dùng khóa giả (Không làm gì cả)
struct NullMutex {
void lock() {}
void unlock() {}
};
struct SingleThreadPolicy {
using mutex_t = NullMutex; // Định nghĩa mutex_t là khóa giả
};
Bước 2: Thiết kế class chính dựa trên chính sách (Host class)
Class logger của chúng ta bây giờ không tự quyết định loại khóa nữa. Nó nhận một gói chính sách thông qua temlate
template <typename ThreadingPolicy>
class Logger {
private:
// Logger không biết mutex_t là gì, nó chỉ lấy ra từ gói ThreadingPolicy
using mtx_type = typename ThreadingPolicy::mutex_t;
mtx_type mutex_;
public:
void log(std::string msg) {
mutex_.lock(); // Cứ gọi lock!
std::cout << msg << std::endl;
mutex_.unlock(); // Cứ gọi unlock!
}
};
Bước 3:
int main() {
// Bản Logger an toàn cho đa luồng
Logger<MultiThreadPolicy> safe_logger;
safe_logger.log("Hello Multi-thread");
// Bản Logger siêu nhanh cho đơn luồng
Logger<SingleThreadPolicy> fast_logger;
fast_logger.log("Hello Single-thread");
}
/**
* Một mini project hoàn chỉnh áp dụng Policy-Based Design (Thiết kế dựa trên chính sách) trong C++,
* giải quyết bài toán thực tế: Hệ thống Xử lý & Thanh toán Đơn hàng Đa kênh (Multi-Channel Order
* Processing & Payment Gateway).
Bài toán thực tế
Khi xây dựng một hệ thống E-commerce lớn, một đơn hàng (Order) cần được xử lý qua nhiều bước với các yêu
cầu nghiệp vụ khác nhau tùy thuộc vào đối tượng khách hàng (Nội địa hay Quốc tế), loại hình thanh toán
(Ví điện tử, Thẻ tín dụng, Tiền mã hóa) và phương thức vận chuyển (Hỏa tốc, Tiết kiệm).
Nếu dùng OOP truyền thống (Inheritance/Virtual functions), bạn sẽ chìm trong cây kế thừa phức tạp hoặc
các câu lệnh if-else khổng lồ. Policy-Based Design giải quyết việc này bằng cách tách rời các khía cạnh
độc lập thành các lớp chính sách (Policies) và lắp ghép chúng tại thời điểm biên dịch thông qua
Template Metaprogramming, đạt hiệu năng tối đa (Zero-overhead cost).
*/
#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
// ==========================================
// ĐỊNH NGHĨA CẤU TRÚC DỮ LIỆU ĐƠN HÀNG
// ==========================================
struct Order {
std::string order_id;
std::string customer_name;
double base_amount;
std::string currency;
};
// ==========================================
// 1. CÁC CHÍNH SÁCH XỬ LÝ THUẾ & GIẢM GIÁ (PRICING & TAX POLICY)
// ==========================================
struct DomesticVatPolicy {
static double calculate_final_amount(double base_amount) {
// Thuế nội địa VAT 10% + Phí bảo vệ môi trường cố định 5$
double total = base_amount * 1.10 + 5.0;
std::cout << " [TaxPolicy] Áp dụng thuế nội địa VAT 10% + Phí phụ thu.\n";
return total;
}
};
struct InternationalTaxPolicy {
static double calculate_final_amount(double base_amount) {
// Thuế xuất nhập khẩu quốc tế 20% + Phí hải quan 15$
double total = base_amount * 1.20 + 15.0;
std::cout << " [TaxPolicy] Áp dụng thuế quốc tế 20% + Phí hải quan.\n";
return total;
}
};
struct VipMemberTaxPolicy {
static double calculate_final_amount(double base_amount) {
// Thành viên VIP được miễn phí phụ thu và giảm giá 15% trên tổng hóa đơn
double total = base_amount * 0.85;
std::cout << " [TaxPolicy] Áp dụng chính sách VIP: Giảm 15% tổng đơn hàng.\n";
return total;
}
};
// ==========================================
// 2. CÁC CHÍNH SÁCH THANH TOÁN (PAYMENT GATEWAY POLICY)
// ==========================================
struct CreditCardPaymentPolicy {
static bool process_payment(double amount, const std::string& currency) {
std::cout << " [PaymentPolicy] Kết nối Visa/MasterCard Gateway...\n";
std::cout << " [PaymentPolicy] Đã thanh toán thành công " << amount << " " << currency << " qua Thẻ tín dụng.\n";
return true;
}
};
struct CryptoPaymentPolicy {
static bool process_payment(double amount, const std::string& currency) {
std::cout << " [PaymentPolicy] Đang xác thực mạng lưới Blockchain (Gas fee tối ưu)...\n";
std::cout << " [PaymentPolicy] Đã nhận thanh toán quy đổi giá trị " << amount << " " << currency << " qua Crypto (USDT/BTC).\n";
return true;
}
};
struct EWalletPaymentPolicy {
static bool process_payment(double amount, const std::string& currency) {
std::cout << " [PaymentPolicy] Kết nối Ví điện tử (Momo/ZaloPay/PayPal)...\n";
std::cout << " [PaymentPolicy] Giao dịch thành công " << amount << " " << currency << " tức thì.\n";
return true;
}
};
// ==========================================
// 3. CÁC CHÍNH SÁCH VẬN CHUYỂN & LOGISTICS (LOGISTICS POLICY)
// ==========================================
struct ExpressShippingPolicy {
static void dispatch(const Order& order) {
std::cout << " [LogisticsPolicy] Đóng gói bọc thép chuyên dụng.\n";
std::cout << " [LogisticsPolicy] Giao hàng Hỏa tốc (Air Freight) cho đơn hàng " << order.order_id << " của " << order.customer_name << ".\n";
}
};
struct EcoShippingPolicy {
static void dispatch(const Order& order) {
std::cout << " [LogisticsPolicy] Đóng gói bằng vật liệu tái chế sinh học.\n";
std::cout << " [LogisticsPolicy] Giao hàng tiết kiệm đường bộ cho đơn hàng " << order.order_id << " của " << order.customer_name << ".\n";
}
};
// ==========================================
// 4. CÁC CHÍNH SÁCH THÔNG BÁO KHÁCH HÀNG (NOTIFICATION POLICY)
// ==========================================
struct EmailNotificationPolicy {
static void send_notification(const Order& order, double final_amount) {
std::cout << " [NotifyPolicy] Gửi Email xác nhận hóa đơn tổng tiền " << final_amount << " " << order.currency << " tới khách hàng.\n";
}
};
struct TelegramAndEmailNotificationPolicy {
static void send_notification(const Order& order, double final_amount) {
std::cout << " [NotifyPolicy] Gửi Email xác nhận hóa đơn.\n";
std::cout << " [NotifyPolicy] Bắn tin nhắn Telegram Bot thông báo biến động số dư tới khách hàng và quản lý kho.\n";
}
};
// ==========================================
// 5. HOST CLASS (NGỮ CẢNH CHÍNH) LẮP GHÉP HỆ THỐNG
// ==========================================
template <typename TaxPolicy,
typename PaymentPolicy,
typename LogisticsPolicy,
typename NotificationPolicy>
class OrderProcessor : public TaxPolicy,
public PaymentPolicy,
public LogisticsPolicy,
public NotificationPolicy {
public:
void execute_order(const Order& order) {
std::cout << "==========================================\n";
std::cout << "BẮT ĐẦU XỬ LÝ ĐƠN HÀNG: " << order.order_id << "\n";
std::cout << "Khách hàng: " << order.customer_name << " | Giá trị gốc: " << order.base_amount << " " << order.currency << "\n";
std::cout << "------------------------------------------\n";
// Bước 1: Tính toán chi phí thuế và phụ thu dựa trên TaxPolicy
double final_amount = TaxPolicy::calculate_final_amount(order.base_amount);
// Bước 2: Xử lý thanh toán qua PaymentPolicy
bool is_paid = PaymentPolicy::process_payment(final_amount, order.currency);
if (!is_paid) {
std::cout << " [LỖI] Thanh toán thất bại! Hủy đơn hàng.\n";
return;
}
// Bước 3: Điều phối kho và vận chuyển qua LogisticsPolicy
LogisticsPolicy::dispatch(order);
// Bước 4: Gửi thông báo qua NotificationPolicy
NotificationPolicy::send_notification(order, final_amount);
std::cout << "ĐƠN HÀNG HOÀN TẤT THÀNH CÔNG!\n";
std::cout << "==========================================\n\n";
}
};
// ==========================================
// HÀM MAIN - MÔ PHỎNG CÁC NGHIỆP VỤ THỰC TẾ
// ==========================================
int main() {
// Kịch bản 1: Khách hàng nội địa mua hàng giá trị cao, thanh toán ví điện tử, ship hỏa tốc, nhận email
{
Order o1{"ORD-2026-001", "Nguyen Van A", 150.0, "USD"};
OrderProcessor<DomesticVatPolicy,
EWalletPaymentPolicy,
ExpressShippingPolicy,
EmailNotificationPolicy> processor;
processor.execute_order(o1);
}
// Kịch bản 2: Khách hàng quốc tế mua hàng, thanh toán bằng Tiền mã hóa (Crypto), ship tiết kiệm, nhận thông báo đa kênh (Email + Telegram)
{
Order o2{"ORD-2026-002", "John Doe", 850.0, "USD"};
OrderProcessor<InternationalTaxPolicy,
CryptoPaymentPolicy,
EcoShippingPolicy,
TelegramAndEmailNotificationPolicy> processor;
processor.execute_order(o2);
}
// Kịch bản 3 (Tổ hợp độc lạ): Khách hàng VIP thành viên, dùng thẻ tín dụng, ship hỏa tốc, thông báo đa kênh
{
Order o3{"ORD-2026-003", "Tran Thi B", 1200.0, "USD"};
OrderProcessor<VipMemberTaxPolicy,
CreditCardPaymentPolicy,
ExpressShippingPolicy,
TelegramAndEmailNotificationPolicy> processor;
processor.execute_order(o3);
}
return 0;
}
All Rights Reserved