C++常用设计模式之策略模式
序言
策略模式是指定义一系列的算法,把它们一个个的封装起来,并且使它们可以互相替换。本模式可以使得算法独立于它的客户而变化。也就是说这些算法完成的功能一样,对外的接口一样,只是各自实现实现上存在差异。用策略模式来封装算法,效果比较好。
下面以高速缓存(Cache)的替换算法为例,实现策略模式。
所谓Cache的替换算法,就是当Cache发生缺失时,Cache控制器必须选择Cache中的一行并用欲获得的数据替换它。所采用的选择策略就是Cache的替换算法。相应的UML类图如下:

算法定义
这里首先给出算法的定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class ReplaceAlgorithm { public: virtual void replace() = 0; };
class LRU_ReplaceAlgorithm : public ReplaceAlgorithm { public: void repace() { cout<<"Least Recently Used replace algorithm"<<endl; } };
class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm { public: void repace() { cout<<"First in First out replace algorithm"<<endl; } };
class Random_ReplaceAlgorithm : public ReplaceAlgorithm { public: void repace() { cout<<"Random replace algorithm"<<endl; } };
|
实现方式1
接着给出Cache的定义,这里很关键,Cache的实现方式直接影响了客户的使用方式,其关键在于怎么指定替换算法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Cache { public: Cache(ReplaceAlgorithm *ra) { m_ra = ra; } ~Cache() { delete m_ra; m_ra = nullptr; }
void Replace() { m_ra->replace(); }
private: ReplaceAlgorithm *m_ra; }
int main(void) { Cache cache(new LRU_ReplaceAlgorithm()); cache.Replace(); return 0; }
|
这种方式暴露给了客户具体的算法的定义。
实现方式2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
enum RA {LRU, FIFO, RANDOM};
class Cache { private: ReplaceAlgorithm *m_ra; public: Cache(enum RA ra) { if(ra == LRU) m_ra = new LRU_ReplaceAlgorithm(); else if(ra == FIFO) m_ra = new FIFO_ReplaceAlgorithm(); else if(ra == RANDOM) m_ra = new Random_ReplaceAlgorithm(); else m_ra = NULL; } ~Cache() { delete m_ra; } void Replace() { m_ra->Replace(); } };
int main() { Cache cache(LRU); cache.Replace(); return 0; }
|
这种方式也是通过参数指定,不过不是传入指针,而是传入算法的枚举。这样客户就不需要知道算法的具体定义,只需要知道算法的标签即可。
实现方式3
以上两种实现方式都需要构造函数传参才能实现,是否可以不需要构造函数传参的方式来实现?
利用模板来实现。算法通过模板的实参指定,虽然还是使用了参数,但是不是构造函数的参数。在策略模式中,参数的传递难以避免,客户必须指定某种算法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| template <class RA> class Cache { private: RA m_ra; public: Cache(){} ~Cache(){} void Replace() { m_ra.repalce(); } }
int main(void) { Cache <Random_ReplaceAlgorithm> cache; cache.replace(); return 0; }
|