一、背景
在实际应用中,我们经常会遇到需要根据不同条件选择不同算法或行为的情况。传统的做法通常是使用条件语句(例如if-else或switch-case)来根据不同的条件执行不同的逻辑。然而,这种方式存在以下问题:
- 条件语句会使代码变得复杂,并且随着条件的增加而导致代码重复。
- 如果需要更改或添加新的算法或行为,就需要修改原有的代码,这不符合开闭原则(对扩展开放,对修改关闭)。
为了解决这个问题,可以使用策略模式将各个算法或行为封装成独立的策略类,客户端根据需求来选择或切换策略。
二、核心概念
UML类图
策略抽象类(Strategy)和具体策略类
将类中经常变化的算法或者行为,抽离出来成为一个抽象类向外提供接口。具体策略类实现了策略接口,并封装了具体的算法或行为。
策略选择类(Context)
策略选择类持有一个策略抽象类的引用,并通过该接口与具体策略类交互。策略选择类通常包含一个设置策略的方法,用于在运行时动态切换或选择策略。
客户端使用策略选择类的方法来设置或改变所需的策略。并且调用相应方法执行算法或行为。
三、代码实现
策略类、实现类以及策略选择类
class Plan
{
public:
virtual void plan() = 0;
};
class PlayGame : public Plan
{
void plan()
{
std::cout << "play game" << std::endl;
}
};
class ReadBook : public Plan
{
void plan()
{
std::cout << "read book" << std::endl;
}
};
class Walk : public Plan
{
void plan()
{
std::cout << "walk" << std::endl;
}
};
class Person
{
public :
Person() {}
void setPlan(Plan *p)
{
this->p = p;
}
void plan()
{
if(p)
p->plan();
}
private:
Plan *p;
}
客户端
int main(void)
{
Person person;
person.setPlan(new PlayGame);
person.plan();
person.setPlan(new ReadBook);
person.plan();
person.setPlan(new Walk);
person.plan();
return 0;
}
四、优点和适用性分析
遵守的原则
策略模式符合开闭原则,可以方便地添加新的策略类而无需修改现有代码。
策略模式也符合单一职责原则,每个算法或行为都被封装到独立的策略类中。
通过使用接口和抽象类,策略模式可以支持依赖倒置原则。
优点
策略模式使得代码结构更清晰,策略类的相互替换和新增都更加方便。使得算法或行为的变化与其他代码部分解耦,降低了代码的复杂性。允许在运行时动态选择策略,使得系统更加灵活和可配置。
适用性
当需要根据不同的条件选择不同的算法或行为时,又或者多个类似的条件语句存在时,可以考虑使用策略模式来避免代码重复和维护困难。
五、总结
策略模式是一种实用的设计模式,可以将复杂的问题分解为更小的部分,并提供了更好的扩展性。
在实际应用中,需要根据具体需求和系统复杂性来灵活选择是否使用策略模式。在一些简单的情况小使用策略模式,反而会增加代码的复杂性。