C++设计模式:策略模式(商品价格促销系统)
·
什么是策略模式?
策略模式是一种行为型设计模式,它的核心目的是将一组算法封装起来,让它们可以互相替换,并使算法的变化独立于使用它的客户端代码。
通俗解释:
- 假设你有一个应用程序需要根据用户的不同需求,动态选择不同的行为,比如:
- 不同的付款方式(如支付宝、微信、信用卡支付)。
- 不同的排序算法(如快速排序、冒泡排序)。
- 不同的促销策略(如满减、打折、返现)。
通过策略模式,你可以将这些算法(或行为)抽象出来,每种算法用一个类来实现,然后在运行时动态选择需要的算法,而无需修改客户端代码。
策略模式的结构
UML类图
+----------------+
| Context | // 上下文环境类
+----------------+
|
|
+----------------+
| Strategy | // 策略抽象类
+----------------+
^
|
+----------------------------------+
| | |
+--------------+ +--------------+ +--------------+
| ConcreteStrategyA| ConcreteStrategyB| ConcreteStrategyC|
| 具体策略A | 具体策略B | 具体策略C |
+--------------+ +--------------+ +--------------+
组成
-
Strategy(策略接口):
定义所有策略的统一接口,使得不同策略可以互相替换。 -
ConcreteStrategy(具体策略):
实现具体的算法或行为。 -
Context(上下文环境类):
持有一个Strategy对象的引用,调用策略对象的方法完成具体的任务。 -
客户端(Client):
负责选择并设置具体的策略,或者将策略传递给上下文环境类。
策略模式的核心思想
策略模式的核心思想是分离算法的定义和使用。客户端代码不需要知道具体的算法细节,只需要知道策略接口。这样可以通过不同的策略实现类,在运行时灵活切换行为,而不用修改客户端代码。
策略模式的优点和缺点
优点
- 开闭原则:可以方便地增加新的策略,而无需修改已有代码。
- 减少代码耦合:将算法和使用算法的代码解耦,便于维护。
- 提高代码灵活性:可以在运行时动态选择不同的算法。
缺点
- 类的数量增加:每个策略都需要定义一个类,可能会导致类的数量较多。
- 客户端必须知道所有的策略:客户端需要清楚有哪些策略可以选择。
案例:商品价格促销系统
需求描述
我们需要设计一个商品促销系统,支持以下促销策略:
- 正常价格(无折扣)
- 满减(满100减20)
- 打折(7折优惠)
目标
- 使用策略模式实现上述需求,能够在运行时动态选择促销策略。
- 输出信息使用中文以便理解。
代码实现
#include <iostream>
#include <memory>
// 策略接口:定义计算价格的统一接口
class PricingStrategy {
public:
virtual double calculatePrice(double originalPrice) const = 0; // 定义统一的价格计算方法
virtual ~PricingStrategy() = default;
};
// 具体策略1:正常价格(无折扣)
class NormalPricing : public PricingStrategy {
public:
double calculatePrice(double originalPrice) const override {
std::cout << "正常价格,无折扣。" << std::endl;
return originalPrice;
}
};
// 具体策略2:满减(满100减20)
class FullReductionPricing : public PricingStrategy {
public:
double calculatePrice(double originalPrice) const override {
if (originalPrice >= 100) {
std::cout << "满减促销:满100减20。" << std::endl;
return originalPrice - 20;
} else {
std::cout << "未达到满减条件,原价结算。" << std::endl;
return originalPrice;
}
}
};
// 具体策略3:打折(7折优惠)
class DiscountPricing : public PricingStrategy {
public:
double calculatePrice(double originalPrice) const override {
std::cout << "打折促销:7折优惠。" << std::endl;
return originalPrice * 0.7;
}
};
// 上下文环境类:使用促销策略来计算价格
class ShoppingCart {
private:
std::shared_ptr<PricingStrategy> strategy; // 持有一个策略对象的引用
public:
// 设置策略
void setPricingStrategy(std::shared_ptr<PricingStrategy> newStrategy) {
strategy = newStrategy;
}
// 计算价格
double calculateTotal(double originalPrice) const {
if (strategy) {
return strategy->calculatePrice(originalPrice);
} else {
std::cerr << "错误:未设置促销策略!" << std::endl;
return originalPrice;
}
}
};
// 客户端代码
int main() {
ShoppingCart cart; // 创建购物车
// 原价
double originalPrice = 150.0;
// 使用正常价格策略
cart.setPricingStrategy(std::make_shared<NormalPricing>());
std::cout << "最终价格: " << cart.calculateTotal(originalPrice) << " 元" << std::endl;
// 使用满减策略
cart.setPricingStrategy(std::make_shared<FullReductionPricing>());
std::cout << "最终价格: " << cart.calculateTotal(originalPrice) << " 元" << std::endl;
// 使用打折策略
cart.setPricingStrategy(std::make_shared<DiscountPricing>());
std::cout << "最终价格: " << cart.calculateTotal(originalPrice) << " 元" << std::endl;
return 0;
}
运行结果
正常价格,无折扣。
最终价格: 150 元
满减促销:满100减20。
最终价格: 130 元
打折促销:7折优惠。
最终价格: 105 元
代码讲解
1. 策略接口(PricingStrategy)
class PricingStrategy {
public:
virtual double calculatePrice(double originalPrice) const = 0;
virtual ~PricingStrategy() = default;
};
- 定义了一个统一的价格计算接口。
- 所有的具体策略类都需要实现
calculatePrice方法。
2. 具体策略类
class NormalPricing : public PricingStrategy {
public:
double calculatePrice(double originalPrice) const override {
std::cout << "正常价格,无折扣。" << std::endl;
return originalPrice;
}
};
NormalPricing:实现了正常价格策略,返回原价。FullReductionPricing:实现了满减策略,满足条件则减去20元。DiscountPricing:实现了7折优惠策略。
每个具体策略类只实现自己的算法,彼此独立。
3. 上下文环境类(ShoppingCart)
class ShoppingCart {
private:
std::shared_ptr<PricingStrategy> strategy;
public:
void setPricingStrategy(std::shared_ptr<PricingStrategy> newStrategy) {
strategy = newStrategy;
}
double calculateTotal(double originalPrice) const {
if (strategy) {
return strategy->calculatePrice(originalPrice);
} else {
std::cerr << "错误:未设置促销策略!" << std::endl;
return originalPrice;
}
}
};
- 上下文类
ShoppingCart持有一个策略对象的引用,通过setPricingStrategy方法动态设置策略。 calculateTotal方法调用当前策略的calculatePrice方法完成价格计算。
4. 客户端代码
cart.setPricingStrategy(std::make_shared<NormalPricing>());
std::cout << "最终价格: " << cart.calculateTotal(originalPrice) << " 元" << std::endl;
- 客户端通过
setPricingStrategy方法动态选择策略。 - 可以在运行时切换不同的策略,灵活应对不同的促销规则。
策略模式的优缺点
优点
- 开闭原则:可以轻松添加新的策略,而无需修改现有代码。
- 灵活扩展:通过动态设置策略,可以灵活切换行为。
- 代码解耦:将算法的实现与算法的使用分离,提高代码的可维护性。
缺点
- 策略类增多:每个策略需要定义一个类,当策略较多时,会增加类的数量。
- 客户端必须了解策略:客户端需要知道有哪些策略可以选择。
总结
策略模式是一种非常灵活的设计模式,通过将算法封装为独立的类,使得算法可以独立扩展和替换。
更多推荐
所有评论(0)