设计模式 | 策略模式
·
策略模式(Strategy Pattern)是行为型设计模式中的算法封装大师,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。这种模式让算法的变化独立于使用算法的客户端,实现了算法与客户端的解耦。本文将深入探索策略模式的核心思想、实现技巧以及在C++中的高效实践。
为什么需要策略模式?
在软件开发中,算法选择是常见需求:
-
支付系统的多种支付方式(信用卡、PayPal、加密货币)
-
导航系统的不同路径规划(最快、最短、避开高速)
-
数据压缩的不同算法(ZIP、RAR、7z)
-
排序算法的动态选择(快速排序、归并排序、堆排序)
-
渲染引擎的不同渲染策略(光线追踪、光栅化)
硬编码算法选择会导致:
条件爆炸:复杂的if-else或switch-case语句
维护困难:添加新算法需修改现有代码
紧耦合:业务逻辑与算法实现混杂
复用性差:算法难以单独复用
策略模式通过封装算法族解决了这些问题。
策略模式的核心概念
模式结构解析
[上下文] → [策略接口]
▲
|
[具体策略A] [具体策略B]
关键角色定义
-
上下文(Context)
-
维护策略对象的引用
-
提供设置策略的接口
-
将请求委托给当前策略对象
-
-
策略接口(Strategy)
-
定义算法族的公共接口
-
声明算法执行方法
-
-
具体策略(Concrete Strategy)
-
实现策略接口
-
封装具体算法实现
-
C++实现:电商支付处理系统
实现支持多种支付方式且可扩展的支付系统:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <stdexcept>
#include <ctime>
#include <iomanip>
#include <cmath>
// ================= 支付策略接口 =================
class PaymentStrategy {
public:
virtual ~PaymentStrategy() = default;
virtual bool processPayment(double amount) = 0;
virtual std::string getStrategyName() const = 0;
virtual void displayDetails() const = 0;
};
// ================= 具体策略:信用卡支付 =================
class CreditCardPayment : public PaymentStrategy {
public:
CreditCardPayment(const std::string& cardNumber,
const std::string& expiryDate,
const std::string& cvv)
: cardNumber_(maskCardNumber(cardNumber)),
expiryDate_(expiryDate),
cvv_(cvv) {}
bool processPayment(double amount) override {
std::cout << "处理信用卡支付..." << std::endl;
std::cout << "验证卡信息: " << cardNumber_ << " 有效期: " << expiryDate_ << std::endl;
// 模拟支付处理
std::cout << "向银行发送支付请求: ¥" << amount << std::endl;
simulateNetworkDelay();
// 模拟90%成功率
if (rand() % 100 < 90) {
std::cout << "信用卡支付成功!\n";
return true;
}
std::cout << "信用卡支付失败: 银行拒绝交易\n";
return false;
}
std::string getStrategyName() const override {
return "信用卡支付";
}
void displayDetails() const override {
std::cout << "信用卡: " << cardNumber_
<< " 有效期: " << expiryDate_ << std::endl;
}
private:
static std::string maskCardNumber(const std::string& cardNumber) {
if (cardNumber.length() < 12) return "****-****-****-****";
return "****-****-****-" + cardNumber.substr(cardNumber.length() - 4);
}
void simulateNetworkDelay() {
std::cout << "与银行通信中...";
for (int i = 0; i < 3; ++i) {
std::cout << "." << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
std::cout << std::endl;
}
std::string cardNumber_;
std::string expiryDate_;
std::string cvv_;
};
// ================= 具体策略:PayPal支付 =================
class PayPalPayment : public PaymentStrategy {
public:
explicit PayPalPayment(const std::string& email)
: email_(email) {}
bool processPayment(double amount) override {
std::cout << "处理PayPal支付..." << std::endl;
std::cout << "账户: " << email_ << std::endl;
// 模拟支付处理
std::cout << "重定向到PayPal登录页面" << std::endl;
simulateUserInteraction();
// 模拟85%成功率
if (rand() % 100 < 85) {
std::cout << "PayPal支付成功!\n";
return true;
}
std::cout << "PayPal支付失败: 用户取消\n";
return false;
}
std::string getStrategyName() const override {
return "PayPal支付";
}
void displayDetails() const override {
std::cout << "PayPal账户: " << email_ << std::endl;
}
private:
void simulateUserInteraction() {
std::cout << "用户登录中...";
for (int i = 0; i < 5; ++i) {
std::cout << "." << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
std::cout << "\n用户确认支付 ¥" << std::fixed << std::setprecision(2)
<< amount_ << std::endl;
}
std::string email_;
double amount_ = 0.0;
};
// ================= 具体策略:加密货币支付 =================
class CryptoPayment : public PaymentStrategy {
public:
CryptoPayment(const std::string& walletAddress,
const std::string& currency = "BTC")
: walletAddress_(walletAddress),
currency_(currency) {}
bool processPayment(double amount) override {
std::cout << "处理加密货币支付..." << std::endl;
std::cout << "钱包地址: " << walletAddress_ << std::endl;
// 转换为加密货币
double cryptoAmount = convertToCrypto(amount);
std::cout << "转换金额: ¥" << amount << " → "
<< cryptoAmount << " " << currency_ << std::endl;
// 模拟区块链交易
simulateBlockchainTransaction();
// 模拟75%成功率
if (rand() % 100 < 75) {
std::cout << "加密货币支付成功!\n";
return true;
}
std::cout << "加密货币支付失败: 交易超时\n";
return false;
}
std::string getStrategyName() const override {
return currency_ + "支付";
}
void displayDetails() const override {
std::cout << currency_ << "钱包: " << walletAddress_ << std::endl;
}
private:
double convertToCrypto(double amount) {
// 模拟汇率转换
double exchangeRate = 0.000025; // 1 CNY = 0.000025 BTC
if (currency_ == "ETH") exchangeRate = 0.00038;
else if (currency_ == "LTC") exchangeRate = 0.0032;
return amount * exchangeRate;
}
void simulateBlockchainTransaction() {
std::cout << "等待区块链确认...\n";
for (int i = 0; i < 6; ++i) {
std::cout << "区块" << (i+1) << "/6 确认中..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(700));
}
}
std::string walletAddress_;
std::string currency_;
};
// ================= 上下文:订单处理器 =================
class OrderProcessor {
public:
explicit OrderProcessor(double amount) : amount_(amount) {}
void setPaymentStrategy(std::unique_ptr<PaymentStrategy> strategy) {
strategy_ = std::move(strategy);
std::cout << "支付方式设置为: " << strategy_->getStrategyName() << std::endl;
}
bool processOrder() {
if (!strategy_) {
throw std::runtime_error("未设置支付策略");
}
std::cout << "\n===== 处理订单 =====" << std::endl;
std::cout << "订单金额: ¥" << std::fixed << std::setprecision(2) << amount_ << std::endl;
strategy_->displayDetails();
return strategy_->processPayment(amount_);
}
void addDiscount(double discount) {
amount_ -= discount;
std::cout << "应用折扣: ¥" << discount << " | 新金额: ¥" << amount_ << std::endl;
}
void addTax(double taxRate) {
double tax = amount_ * taxRate;
amount_ += tax;
std::cout << "添加税费: ¥" << tax << " | 新金额: ¥" << amount_ << std::endl;
}
private:
double amount_;
std::unique_ptr<PaymentStrategy> strategy_;
};
// ================= 策略工厂 =================
class PaymentStrategyFactory {
public:
static std::unique_ptr<PaymentStrategy> createStrategy(
const std::string& type,
const std::map<std::string, std::string>& params) {
if (type == "credit_card") {
return std::make_unique<CreditCardPayment>(
params.at("card_number"),
params.at("expiry_date"),
params.at("cvv"));
}
else if (type == "paypal") {
return std::make_unique<PayPalPayment>(params.at("email"));
}
else if (type == "crypto") {
return std::make_unique<CryptoPayment>(
params.at("wallet_address"),
params.value("currency", "BTC"));
}
throw std::invalid_argument("未知支付类型: " + type);
}
};
// ================= 客户端代码 =================
int main() {
srand(time(nullptr)); // 初始化随机种子
// 创建订单
OrderProcessor order(999.99);
order.addDiscount(100.0); // 满减折扣
order.addTax(0.08); // 8%税费
// 用户选择支付方式
int choice;
std::cout << "请选择支付方式:\n"
<< "1. 信用卡支付\n"
<< "2. PayPal支付\n"
<< "3. 加密货币支付\n"
<< "输入选择: ";
std::cin >> choice;
// 根据选择设置策略
std::map<std::string, std::string> params;
switch (choice) {
case 1: {
std::string card, expiry, cvv;
std::cout << "输入信用卡号: ";
std::cin >> card;
std::cout << "输入有效期 (MM/YY): ";
std::cin >> expiry;
std::cout << "输入CVV: ";
std::cin >> cvv;
params = {{"card_number", card}, {"expiry_date", expiry}, {"cvv", cvv}};
order.setPaymentStrategy(
PaymentStrategyFactory::createStrategy("credit_card", params));
break;
}
case 2: {
std::string email;
std::cout << "输入PayPal邮箱: ";
std::cin >> email;
params = {{"email", email}};
order.setPaymentStrategy(
PaymentStrategyFactory::createStrategy("paypal", params));
break;
}
case 3: {
std::string wallet, currency;
std::cout << "输入钱包地址: ";
std::cin >> wallet;
std::cout << "输入加密货币类型 (BTC/ETH/LTC, 默认为BTC): ";
std::cin >> currency;
params = {{"wallet_address", wallet}};
if (!currency.empty()) params["currency"] = currency;
order.setPaymentStrategy(
PaymentStrategyFactory::createStrategy("crypto", params));
break;
}
default:
std::cerr << "无效选择!" << std::endl;
return 1;
}
// 处理订单
bool success = order.processOrder();
// 处理结果
if (success) {
std::cout << "\n 订单处理成功! 感谢您的购买。\n";
} else {
std::cout << "\n 订单处理失败! 请尝试其他支付方式。\n";
// 策略切换示例
std::cout << "尝试使用PayPal支付...\n";
std::string email = "customer@example.com";
order.setPaymentStrategy(std::make_unique<PayPalPayment>(email));
success = order.processOrder();
if (success) {
std::cout << "\n 使用PayPal支付成功!\n";
}
}
return 0;
}
策略模式的五大优势
-
算法封装
// 每个算法独立封装 class QuickSort : public SortStrategy { void sort(DataSet& data) override { // 快速排序实现 } }; -
运行时切换
// 动态改变策略 context.setStrategy(new PayPalStrategy()); -
消除条件语句
// 代替switch-case paymentStrategy->process(amount); -
开放封闭原则
// 添加新策略不影响现有代码 class CryptoStrategy : public PaymentStrategy { // 新支付算法 }; -
算法复用
// 相同策略可用于不同上下文 orderProcessor.setStrategy(creditCardStrategy); donationProcessor.setStrategy(creditCardStrategy);
策略模式的高级应用
1. 策略组合
class CompositeStrategy : public PaymentStrategy {
public:
void addStrategy(std::unique_ptr<PaymentStrategy> strategy) {
strategies_.push_back(std::move(strategy));
}
bool processPayment(double amount) override {
double remaining = amount;
for (auto& strategy : strategies_) {
double partial = std::min(remaining, maxAmountFor(strategy));
if (!strategy->processPayment(partial)) return false;
remaining -= partial;
if (remaining <= 0) break;
}
return true;
}
private:
std::vector<std::unique_ptr<PaymentStrategy>> strategies_;
};
// 使用
auto composite = std::make_unique<CompositeStrategy>();
composite->addStrategy(std::make_unique<CreditCardPayment>(...));
composite->addStrategy(std::make_unique<PayPalPayment>(...));
order.setPaymentStrategy(std::move(composite));
2. 策略自动选择
class SmartPaymentSelector {
public:
void processPayment(double amount) {
auto strategy = selectBestStrategy(amount);
strategy->processPayment(amount);
}
private:
std::unique_ptr<PaymentStrategy> selectBestStrategy(double amount) {
// 基于规则选择最佳策略
if (amount > 5000) return std::make_unique<BankTransferStrategy>();
if (user.hasCryptoPreference()) return std::make_unique<CryptoPayment>();
return std::make_unique<CreditCardPayment>();
}
};
3. 策略性能分析
class ProfiledStrategy : public PaymentStrategy {
public:
explicit ProfiledStrategy(std::unique_ptr<PaymentStrategy> strategy)
: wrapped_(std::move(strategy)) {}
bool processPayment(double amount) override {
auto start = std::chrono::high_resolution_clock::now();
bool result = wrapped_->processPayment(amount);
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << wrapped_->getStrategyName() << " 耗时: "
<< duration.count() << "ms" << std::endl;
return result;
}
private:
std::unique_ptr<PaymentStrategy> wrapped_;
};
// 使用
auto baseStrategy = std::make_unique<CreditCardPayment>(...);
order.setPaymentStrategy(std::make_unique<ProfiledStrategy>(std::move(baseStrategy)));
策略模式的应用场景
1. 导航系统
class NavigationContext {
public:
void setStrategy(std::unique_ptr<RoutingStrategy> strategy) {
strategy_ = std::move(strategy));
}
Route calculateRoute(Point start, Point end) {
return strategy_->calculateRoute(start, end);
}
private:
std::unique_ptr<RoutingStrategy> strategy_;
};
class FastestRouteStrategy : public RoutingStrategy {
Route calculateRoute(Point start, Point end) override {
// 使用实时交通数据
return calculateFastestRoute(start, end);
}
};
class ScenicRouteStrategy : public RoutingStrategy {
Route calculateRoute(Point start, Point end) override {
// 选择风景优美的路线
return calculateScenicRoute(start, end);
}
};
2. 数据压缩工具
class CompressionContext {
public:
void setCompressionStrategy(std::unique_ptr<CompressionStrategy> strategy) {
strategy_ = std::move(strategy));
}
void compressFile(const std::string& filename) {
strategy_->compress(filename);
}
private:
std::unique_ptr<CompressionStrategy> strategy_;
};
class ZipCompression : public CompressionStrategy {
void compress(const std::string& filename) override {
// ZIP压缩实现
std::cout << "使用ZIP算法压缩: " << filename << std::endl;
}
};
class RARCompression : public CompressionStrategy {
void compress(const std::string& filename) override {
// RAR压缩实现
std::cout << "使用RAR算法压缩: " << filename << std::endl;
}
};
3. 游戏AI系统
class AICharacter {
public:
void setBehavior(std::unique_ptr<AIBehavior> behavior) {
behavior_ = std::move(behavior));
}
void update() {
behavior_->execute(*this);
}
private:
std::unique_ptr<AIBehavior> behavior_;
};
class AggressiveBehavior : public AIBehavior {
void execute(AICharacter& character) override {
// 攻击最近的玩家
auto target = findNearestEnemy();
character.attack(target);
}
};
class DefensiveBehavior : public AIBehavior {
void execute(AICharacter& character) override {
// 寻找掩体并治疗
if (character.health < 50) {
character.findCover();
character.heal();
}
}
};
class PatrolBehavior : public AIBehavior {
void execute(AICharacter& character) override {
// 沿预定路径巡逻
character.followPatrolRoute();
}
};
策略模式与其他模式的关系
| 模式 | 关系 | 区别 |
|---|---|---|
| 命令 | 都封装操作 | 命令封装请求,策略封装算法 |
| 工厂 | 常结合创建策略对象 | 工厂创建对象,策略管理算法 |
| 状态 | 结构相似,意图不同 | 状态管理状态转换,策略管理算法选择 |
| 模板方法 | 都涉及算法 | 模板方法固定结构,策略完全替换算法 |
组合使用示例:
// 策略模式 + 工厂模式
class StrategyFactory {
public:
std::unique_ptr<SortStrategy> createSortStrategy(SortType type) {
switch (type) {
case SortType::QUICK: return std::make_unique<QuickSort>();
case SortType::MERGE: return std::make_unique<MergeSort>();
case SortType::HEAP: return std::make_unique<HeapSort>();
default: throw std::invalid_argument("未知排序类型");
}
}
};
// 使用
auto factory = StrategyFactory();
context.setStrategy(factory.createSortStrategy(SortType::MERGE));
策略模式的挑战与解决方案
| 挑战 | 解决方案 |
|---|---|
| 策略类膨胀 | 使用函数对象或lambda表达式 |
| 客户端了解策略细节 | 结合工厂模式封装创建逻辑 |
| 策略间数据共享 | 通过上下文传递共享数据 |
| 动态策略切换开销 | 实现策略对象池 |
Lambda策略示例:
class PaymentContext {
public:
using Strategy = std::function<bool(double)>;
void setStrategy(Strategy strategy) {
strategy_ = std::move(strategy));
}
bool processPayment(double amount) {
return strategy_(amount);
}
private:
Strategy strategy_;
};
// 使用
PaymentContext context;
context.setStrategy([&](double amount) {
std::cout << "处理现金支付: ¥" << amount << std::endl;
return true;
});
context.processPayment(100.0);
总结
策略模式是算法管理的终极解决方案,它通过:
-
算法封装:每个算法独立成类
-
动态切换:运行时改变算法行为
-
解耦设计:分离算法与使用上下文
-
扩展自由:轻松添加新算法
适用场景:
-
需要多种算法变体
-
算法需要自由切换
-
需要消除条件语句
-
算法需要复用和扩展
"策略模式不是简单的算法替换,而是将算法提升为一等公民。它是灵活性的架构基石。" — 设计模式实践者
更多推荐


所有评论(0)