1、策略模式是指定义一系列的算法,把它们一个个封装起来,并使他们可以相互替换,本模式使得算法可以独立于使用它的客户而变化。也就是说这些算法所完成的功能一样,对外接口一样,只是各自实现上存在差异。
2、下面以高速缓存(Cache)的替换算法为例,实现策略模式,什么是Cache的替换算法?当Cache缺失时,Cache控制器必须选择Cache中的一行,并用欲获得的数据来替换它(替换选中的这一行)。如何去选择Cache中的一行,怎样选择然后去进行替换,这个选择的方法就是Cache的替换算法。如FIFO(先进先出),LRU(最近最少使用,Random(随机)等算法。接触过计算机组成原理和计算机操作系统的朋友应该知道这些算法。没接触过的当然也没有关系,你可以当做你要去做一件事情,但是你有多种不同的方法可以完成这件事情,虽然完成的方法不同,但是目的都是将这件事情完成。
#include<iostream>
using namespace std;
//抽象的接口
class ReplaceAlgorithm
{
public:
virtual void Replace() = 0;
};
//三种具体的置换算法
class LRU_ReplaceAlgorithm :public ReplaceAlgorithm
{
public:
void Replace()
{
cout<<"最近最少使用"<<endl;
}
};
class FIFO_ReplaceAlgorithm :public ReplaceAlgorithm
{
public:
void Replace()
{
cout<<"先进先出"<<endl;
}
};
class Random_ReplaceAlgorithm :public ReplaceAlgorithm
{
public:
void Replace()
{
cout<<"随机选择"<<endl;
}
};
//接着给出Cache的定义 这里很关键 Cache的实现方式直接影响了客户的使用方式,其关键在于
//如何指定替换算法
//方式一:直接通过参数指定,传入一个特定的算法指针
class Cache1
{
private:
ReplaceAlgorithm *m_re;
public:
Cache1(ReplaceAlgorithm *re)
{
m_re = re;
}
~Cache1()
{
delete m_re;
}
void Replace()
{
m_re->Replace();
}
};
//如果用这种方法,客户就需要知道这些算法的具体定义,暴露太多细节
//方法二:也是直接通过参数指定,只不过不是传入指针,而是一个标签,这样客户只要
//知道算法相应的标签即可,而不需要知道算法的具体定义
enum RE{LRU,FIFO,RANDOM}; //标签
class Cache2
{
private:
ReplaceAlgorithm *m_re;
public:
Cache2(enum RE re)
{
if(re == LRU)
m_re = new LRU_ReplaceAlgorithm();
else if(re = FIFO)
m_re = new FIFO_ReplaceAlgorithm();
else if(re = RANDOM)
m_re = new Random_ReplaceAlgorithm();
else
m_re = NULL;
}
~Cache2()
{
delete m_re;
}
void Relace()
{
m_re->Replace();
}
};
//相比方式一,这种方式用起来方便很多,这种方式将简单工厂模式与策略模式结合在一起,
//算法的定义使用了策略模式,而Cache的定义使用了简单工厂模式。
int main()
{
//方式一
Cache1 *cache1 = new Cache1(new LRU_ReplaceAlgorithm()); //暴露了算法的定义
cache1->Replace();
//方式二
Cache2 *cache2 = new Cache2(LRU);
cache2->Relace();
return 0;
}
ReplaceAlgorithm是一个抽象类,定义了算法的接口,有三个类继承自这个抽象类,也就是具体的算法实现。Cache类中需要使用替换算法,因此维护了一个ReplaceAlgorithm的对象。这就是策略模式的典型结构。
策略模式侧重于同一个动作,实现该行为的算法的不同,不同的策略封装了不同的算法。策略模式适用于实现某一功能,而实现该功能的算法是经常改变的情况。在实际工作中,遇到了实际的场景,可能会有更深的体会。比如,我们做某一个系统,该系统可以适用于各种数据库,我们都知道,连接某一种数据库的方式是不一样的,也可以说,连接数据库的“算法”都是不一样的。这样我们就可以使用策略模式来实现不同的连接数据库的策略,从而实现数据库的动态变换。
其中部分内容参考于:https://blog.csdn.net/wuzhekai1985/article/details/6665197
https://www.cnblogs.com/ring1992/p/9593575.html