C++实现Behavioral - Strategy模式

【转载】 C++实现Behavioral - Strategy模式
转载自: http://patmusing.blog.163.com/blog/static/1358349602010150224904/

也称为 Policy 模式。

定义一系列算法,把他们一个个封装起来,并且使他们可以相互替换。该模式使得算法可以独立于使用它的客户而变化。

“Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.”- GoF

在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到某个对象中,将会使该对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。Strategy设计模式就是在运行时根据需要透明地更改对象的算法,将算法和对象本身解耦。

我们在编程中,经常碰到这样的情况:用不同的办法去做同一件事情,比如,

1. 将文件保存为不同的格式;

2. 用不同的压缩算法压缩一个文本文件;

3. 用不同的压缩算法压缩视频文件

4. 将同样的数据,用不同的图形显示出来:折线图、柱状图或者饼图;

5. 将用某种语言写的一个句子,翻译成为几种其他的语言。

客户程序告诉驱动模块(不妨称为Context),它将使用哪个算法(即所谓的strategypolicy),并请求Context执行该算法。

Strategy模式UML类图:

 C++实现Behavioral - Strategy模式_第1张图片
v

角色:

Strategy

- 给所有支持的算法声明一个通用接口,Context使用该接口调用由ConcreteStrategy定义的算法。

ConcreteStrategy

- 按照Strategy给出的接口实现具体的算法。

Context

- 包含一个Strategy的引用;

- 可以由ConcreteStrategy对象对其进行配置。

业务示例:

将阿拉伯数字“520”分别翻译成中文、英语和俄语。

下面是具体C++代码:

// Strategy.h

#include <iostream>

#include <string>

#include <memory>

using namespace std;

// Strategy抽象类,用做借口

class Strategy

{

public:

virtual string substitute(string str) = 0;

public:

virtual ~Strategy()

{

cout << "in the destructor of Strategy..." << endl;

}

};

// 中文Strategy

class ChineseStrategy : public Strategy

{

public:

string substitute(string str)

{

size_t index = str.find("520");

string tempstr = str.replace(index, 3, "我爱你");

return tempstr;

}

public:

~ChineseStrategy()

{

cout << "in the destructor of ChineseStrategy..." << endl;

}

};

// 英语Strategy

class EnglishStrategy : public Strategy

{

public:

string substitute(string str)

{

size_t index = str.find("520");

string tempstr = str.replace(index, 3, "I love you");

return tempstr;

}

public:

~EnglishStrategy()

{

cout << "in the destructor of EnglishStrategy..." << endl;

}

};

// 俄语Strategy

class RussianStrategy : public Strategy

{

public:

string substitute(string str)

{

size_t index = str.find("520");

string tempstr = str.replace(index, 3, "Я люблю тебя");

return tempstr;

}

public:

~RussianStrategy()

{

cout << "in the destructor of RussiaStrategy..." << endl;

}

};

// Context

class Translator

{

private:

auto_ptr<Strategy> strategy;

public:

~Translator()

{

cout << "in the destructor of Translator..." << endl;

}

public:

void set_strategy(auto_ptr<Strategy> strategy)

{

this->strategy = strategy;

}

string translate(string str)

{

if(0 == strategy.get()) return "";

return strategy->substitute(str);

}

};

// Strategy.cpp

#include "Strategy.h"

int main(int argc, char** argv)

{

string str("321520");

Translator* translator = new Translator;

// 未指定strategy

cout << "No strategy: " << translator->translate(str) << endl;

cout << "--------------------------" << endl;

// 翻译成中文

auto_ptr<Strategy> s1(new ChineseStrategy());

translator->set_strategy(s1);

cout << "Chinese strategy: " << translator->translate(str) << endl;

cout << "--------------------------" << endl;

// 翻译成英语

auto_ptr<Strategy> s2(new EnglishStrategy());

translator->set_strategy(s2);

cout << "English strategy: " << translator->translate(str) << endl;

cout << "--------------------------" << endl;

// 翻译成俄语

auto_ptr<Strategy> s3(new RussianStrategy());

translator->set_strategy(s3);

cout << "Russian strategy: " << translator->translate(str) << endl;

cout << "--------------------------" << endl;

delete translator;

return 0;

}

运行结果:

No strategy:

--------------------------

Chinese strategy: 321我爱你

--------------------------

in the destructor of ChineseStrategy...

in the destructor of Strategy...

English strategy: 321I love you

--------------------------

in the destructor of EnglishStrategy...

in the destructor of Strategy...

Russian strategy: 321Я люблю тебя

--------------------------

in the destructor of Translator...

in the destructor of RussiaStrategy...

in the destructor of Strategy...

结果符合预期。

1. 从上面程序可以很容易看出,可以在运行时改变translator对象的行为;

2. 算法如果改变了,客户端程序不需要做任何改动,比如在EnglishStrategy的实现中将“520翻译成“Five hundred and twenty”,客户端代码无需任何改变;

3. 当需要增加新的算法时,比如要将“520”翻译成日语的“わたし爱してるあなた”,只需要增加一个具体的Strategy类,比如JapaneseStrategy类,并重写Strategy中声明的纯虚函数即可。这完全符合OCP

上述代码的UML类图:

 C++实现Behavioral - Strategy模式_第2张图片

Strategy模式和State粗看起来非常相似,但他们的意图完全不同。他们主要的区别在于:

1. Strategy一次只能选择一个strategy(即算法),而State模式中,不同的状态有可能同时被激活;

2. Strategy封装的是算法,State封装的是状态;

3. Strategy所封装的算法(每个算法对应一个类),所做的事情相差无几,而State所封装的状态(每个状态对应一个类),往往颇不相同;

4. State模式中的状态迁移的概念,在Strategy中根本不存在。

你可能感兴趣的:( C++实现Behavioral - Strategy模式)