一、定义
定义一系列算法,把它们一个个封装起来,并且使它们可变化。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
二、使用场景
在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明地更改对象的算法,将算法与对象本身解耦?
- 对于性能负担的理解:如果用if else语句,函数会变得很长,这一个函数在同一个代码段,在使用时会整个加载到内存中,但此代码段中又有很长的代码段是不被需要的,这样就占用了内存空间,提高了性能负担。
三、代码对比
背景:公司有许多不同的部门,不同部门之间职责不同。给一个部门,要求输出其职责。
- 一、采用分而治之的算法
enum depart
{
sales,
technology,
product
};
void doWork(int depart)
{
if (depart == 0)
{
cout << "sales" << endl;
}
else if (depart == 1)
{
cout << "technology" << endl;
}
else if (depart == 2)
{
cout << "product" << endl;
}
}
int main()
{
int depart = 1;
doWork(depart);
system("pause");
return 0;
}
当需要增加部门时,需要对源码进行更改。这违背了设计原则:开放封闭原则(对扩展开放,对更改封闭)。
同时,增加了性能负担。
- 二、采用策略模式
class Depart
{
public:
virtual void doWork() = 0;
virtual ~Depart(){};
};
class Sales :public Depart
{
public:
virtual void doWork()
{
cout << "sales" << endl;
}
};
class Technology :public Depart
{
public:
virtual void doWork()
{
cout << "technology" << endl;
}
};
class Product :public Depart
{
public:
virtual void doWork()
{
cout << "product" << endl;
}
};
int main()
{
Depart* dp = new Technology;
dp->doWork();
system("pause");
return 0;
}
此时,当需要增加部门时,只需要对代码进行扩展即可。
并且在运行过程中,不同的算法是动态绑定的,需要谁就去调用谁,而不是先全部加载了。
四、要点总结
- Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。
- Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
- 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。
- 什么时候条件判断语句不需要Strategy模式呢?当条件数目是已知并且不会更改的时候,如一周的每一天做固定的事情。