策略设计模式的功能和作用
策略模式(Strategy Pattern)是一种行为型设计模式,允许在运行时选择算法的行为。它将算法封装成独立的类,使得算法可以独立于客户端变化,增强灵活性和可扩展性。
核心作用包括:
- 解耦算法与客户端:避免在客户端代码中硬编码多种算法。
- 动态切换算法:运行时根据需要替换算法实现。
- 开闭原则支持:新增算法无需修改现有代码。
原理
策略模式基于以下组件:
- Context(上下文):持有具体策略的引用,通过接口调用策略。
- Strategy(策略接口):定义所有支持的算法的公共接口。
- ConcreteStrategy(具体策略):实现策略接口的具体算法类。
使用方式
- 定义策略接口,声明算法方法。
- 实现多个具体策略类。
- 在上下文中注入策略对象,委托其执行算法。
为什么这么设计
- 避免条件分支 :替代大量的
if-else或switch-case语句。 - 单一职责:每个算法独立变化,减少耦合。
- 复用性:策略类可被多个上下文复用。
适用场景
- 系统需要多种算法变体,且可能频繁切换。
- 算法逻辑复杂或需要隔离变化点。
- 避免暴露算法细节给客户端。
类图描述
Context -strategy: Strategy +setStrategy(Strategy) +executeStrategy() <<interface>> Strategy +execute() ConcreteStrategyA +execute() ConcreteStrategyB +execute()
时序图描述
Client Context ConcreteStrategyA setStrategy(ConcreteStrategyA) executeStrategy() execute() Result Result Client Context ConcreteStrategyA
C++代码实现
cpp
#include <iostream>
#include <memory>
// 策略接口
class Strategy {
public:
virtual void execute() const = 0;
virtual ~Strategy() = default;
};
// 具体策略A
class ConcreteStrategyA : public Strategy {
public:
void execute() const override {
std::cout << "Executing Strategy A\n";
}
};
// 具体策略B
class ConcreteStrategyB : public Strategy {
public:
void execute() const override {
std::cout << "Executing Strategy B\n";
}
};
// 上下文
class Context {
private:
std::unique_ptr<Strategy> strategy_;
public:
void setStrategy(std::unique_ptr<Strategy> strategy) {
strategy_ = std::move(strategy);
}
void executeStrategy() const {
if (strategy_) {
strategy_->execute();
}
}
};
// 测试代码
int main() {
Context context;
context.setStrategy(std::make_unique<ConcreteStrategyA>());
context.executeStrategy();
context.setStrategy(std::make_unique<ConcreteStrategyB>());
context.executeStrategy();
return 0;
}
输出结果
Executing Strategy A
Executing Strategy B
优缺点
优点:
- 灵活切换算法,符合开闭原则。
- 避免多重条件语句,代码更清晰。
- 易于单元测试(每个策略独立测试)。
缺点:
- 客户端需了解所有策略类。
- 策略类数量增多时可能增加系统复杂度。
改进方向
-
结合工厂模式:通过工厂创建策略对象,隐藏具体类细节。
-
默认策略:为上下文提供默认实现,减少客户端依赖。
-
Lambda表达式 (C++11+):简化简单策略的实现,例如:
cppcontext.setStrategy([]() { std::cout << "Lambda Strategy\n"; });