1. 策略模式:当if-else开始失控时
上周重构一个图像处理库时,我遇到了一个典型场景:需要支持多种滤镜算法(高斯模糊、边缘检测、锐化等),但不同算法参数和实现差异很大。最初版本用了这样的代码:
cpp复制void applyFilter(Image& img, FilterType type) {
if (type == GAUSSIAN_BLUR) {
// 20行卷积计算代码
}
else if (type == EDGE_DETECTION) {
// 完全不同的矩阵运算
}
// 更多else if...
}
当滤镜类型增加到第5种时,这个函数已经膨胀到200多行,每次新增算法都要修改这个核心类。这正是策略模式要解决的痛点——将算法与使用算法的上下文解耦。
2. 策略模式本质解析
2.1 模式定义与UML结构
策略模式(Strategy Pattern)属于行为型设计模式,其官方定义为:定义一系列算法,将每个算法封装起来,并使它们可以互相替换。其经典UML结构如下:
code复制|----------------| |-------------------|
| Context | | <<Interface>> |
|----------------| | Strategy |
| -strategy:Strategy|<>----|-------------------|
| +executeAlgorithm()| | +algorithm() |
|----------------| |-------------------|
^
________________|_________________
| | |
|---------------| |---------------| |---------------|
| ConcreteStrategyA | | ConcreteStrategyB | | ConcreteStrategyC |
|---------------| |---------------| |---------------|
| +algorithm() | | +algorithm() | | +algorithm() |
|---------------| |---------------| |---------------|
在C++中,这个结构对应着:
- Strategy:抽象基类或接口(纯虚类)
- ConcreteStrategy:具体策略实现类
- Context:持有策略引用的环境类
2.2 模式优势深度分析
相比简单使用条件语句,策略模式具有以下核心优势:
- 开闭原则:新增算法无需修改现有代码
- 单一职责:每个算法有独立类封装
- 运行时切换:动态改变对象行为
- 可测试性:策略类可以单独单元测试
特别在以下场景价值显著:
- 需要多种相似算法变体
- 算法包含复杂条件分支
- 算法需要频繁增减或修改
- 算法具有不同时间/空间复杂度需求
3. C++实现细节剖析
3.1 基础实现模板
cpp复制// 策略接口
class FilterStrategy {
public:
virtual ~FilterStrategy() = default;
virtual void apply(Image& img) const = 0;
};
// 具体策略
class GaussianBlurStrategy : public FilterStrategy {
float sigma_;
public:
explicit GaussianBlurStrategy(float sigma) : sigma_(sigma) {}
void apply(Image& img) const override {
// 实现高斯模糊算法
}
};
// 上下文
class ImageProcessor {
std::unique_ptr<FilterStrategy> strategy_;
public:
void setStrategy(std::unique_ptr<FilterStrategy> strategy) {
strategy_ = std::move(strategy);
}
void process(Image& img) {
if (strategy_) strategy_->apply(img);
}
};
3.2 现代C++优化技巧
使用std::function替代继承
cpp复制using FilterStrategy = std::function<void(Image&)>;
class ImageProcessor {
FilterStrategy strategy_;
public:
void setStrategy(FilterStrategy strategy) {
strategy_ = std::move(strategy);
}
// ...其余相同
};
// 使用lambda注册策略
processor.setStrategy([](Image& img) {
// 直接实现算法
});
策略工厂模式结合
cpp复制class FilterFactory {
public:
static std::unique_ptr<FilterStrategy> create(const std::string& name) {
if (name == "gaussian")
return std::make_unique<GaussianBlu
