Cpp设计模式之策略模式

C++常用设计模式之策略模式

序言

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

算法定义

这里首先给出算法的定义。

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
//Cache需要用到替换算法  

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
//Cache需要用到的替换算法
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;
}