五大创建型设计模式:
单例模式,策略模式,观察者模式,工厂模式,原型模式
策略模式(Strategy Pattern)
策略模式是行为型设计模式,用于定义一系列算法,封装每个算法,并使它们可以互相替换。它让算法独立于使用它的客户端而变化,是面试中高频考察的设计模式之一。
1. 核心概念(背!)
意图:将算法的使用与实现分离,避免多重条件判断,支持开闭原则。
角色:
策略接口(Strategy):定义算法的公共接口。
具体策略(Concrete Strategy):实现策略接口的具体算法。
上下文(Context):持有一个策略对象的引用,通过接口调用算法。
2. 代码示例
场景:电商促销活动,支持多种折扣策略(无折扣、满减、百分比折扣)。
#include <iostream>
#include <memory>
// 1. 策略接口(抽象类)
class DiscountStrategy {
public:
virtual ~DiscountStrategy() = default; // 虚析构确保正确释放资源
virtual double applyDiscount(double originalPrice) const = 0;
};
// 2. 具体策略实现
class NoDiscount : public DiscountStrategy {
public:
double applyDiscount(double price) const override {
return price;
}
};
class FullReductionDiscount : public DiscountStrategy {
private:
double full_;
double reduction_;
public:
FullReductionDiscount(double full, double reduction)
: full_(full), reduction_(reduction) {}
double applyDiscount(double price) const override {
return (price >= full_) ? (price - reduction_) : price;
}
};
class PercentageDiscount : public DiscountStrategy {
private:
double percentage_;
public:
explicit PercentageDiscount(double percentage)
: percentage_(percentage) {}
double applyDiscount(double price) const override {
return price * (1 - percentage_);
}
};
// 3. 上下文(订单类)
class Order {
private:
std::unique_ptr<DiscountStrategy> strategy_; // 使用智能指针管理策略对象
double price_;
public:
Order(double price) : price_(price) {}
void setStrategy(std::unique_ptr<DiscountStrategy> strategy) {
strategy_ = std::move(strategy);
}
double checkout() const {
if (!strategy_) {
throw std::runtime_error("Discount strategy not set!");
}
return strategy_->applyDiscount(price_);
}
};
// 4. 客户端使用
int main() {
Order order(1000.0);
// 设置满减策略:满1000减200
order.setStrategy(std::make_unique<FullReductionDiscount>(1000, 200));
std::cout << "Full Reduction Discount: " << order.checkout() << std::endl; // 输出800
// 切换为百分比折扣:10% off
order.setStrategy(std::make_unique<PercentageDiscount>(0.1));
std::cout << "Percentage Discount: " << order.checkout() << std::endl; // 输出900
return 0;
}
3. C++ 实现关键点
智能指针管理资源:
使用 std::unique_ptr 持有策略对象,避免手动 new/delete,防止内存泄漏。
std::move 转移所有权,确保策略对象生命周期与订单一致。
虚析构函数:
virtual ~DiscountStrategy() = default;
基类声明虚析构函数,确保子类对象通过基类指针销毁时正确释放资源。
常量正确性:
virtual double applyDiscount(double originalPrice) const = 0;
const 修饰成员函数,承诺不修改对象状态,提高代码安全性。
异常处理:
if (!strategy_) {
throw std::runtime_error("Discount strategy not set!");
}
检查策略是否已设置,避免空指针访问。
4. 策略模式在C++中的优势
零成本抽象:C++的策略模式通过虚函数实现动态多态,性能接近手写条件判断。
编译时检查:类型安全,避免运行时类型错误。
与现代C++特性结合:可结合模板、Lambda等实现更灵活的策略(见下文扩展)。
5. 扩展:使用Lambda和模板实现策略模式(C++11+)
若策略简单且无状态,可直接用 std::function 替代抽象类:
#include <functional>
class Order {
private:
std::function<double(double)> strategy_; // 策略为函数对象
double price_;
public:
Order(double price) : price_(price) {}
void setStrategy(std::function<double(double)> strategy) {
strategy_ = strategy;
}
double checkout() const {
if (!strategy_) {
throw std::runtime_error("Strategy not set!");
}
return strategy_(price_);
}
};
// 客户端使用
int main() {
Order order(1000.0);
// 设置满减策略(Lambda表达式)
order.setStrategy([](double price) {
return (price >= 1000) ? (price - 200) : price;
});
std::cout << "Lambda Strategy: " << order.checkout() << std::endl; // 输出800
return 0;
}
6. 面试常见问题
Q1:C++中如何避免策略对象的内存泄漏?
答:使用智能指针(如 std::unique_ptr 或 std::shared_ptr)自动管理资源,避免手动 delete。
Q2:策略模式与模板方法模式的区别?
答:策略模式:通过组合(持有策略对象)实现算法扩展,运行时动态切换。
模板方法模式:通过继承(子类重写虚方法)实现算法扩展,编译时确定行为。
Q3:是否所有策略都需继承自同一个基类?
答:不一定。C++中可通过模板参数或 std::function 实现“鸭子类型”,只要策略对象满足特定接口即可(如拥有 applyDiscount 方法)。
总结
在C++中实现策略模式时,需注意:
资源管理:优先使用智能指针。
多态机制:虚函数实现运行时多态。
现代C++特性:结合Lambda、模板等简化代码。