您的位置:首页 > 编程语言 > C语言/C++

C++实现Behavioral - Strategy模式

2012-02-10 14:04 267 查看
也称为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),它将使用哪个算法(即所谓的strategy或policy),并请求Context执行该算法。

Strategy模式UML类图:



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类图:



Strategy模式和State粗看起来非常相似,但他们的意图完全不同。他们主要的区别在于:
1.
Strategy一次只能选择一个strategy(即算法),而State模式中,不同的状态有可能同时被激活;
2.
Strategy封装的是算法,State封装的是状态;
3.
Strategy所封装的算法(每个算法对应一个类),所做的事情相差无几,而State所封装的状态(每个状态对应一个类),往往颇不相同;
4.
State模式中的状态迁移的概念,在Strategy中根本不存在。

转:http://patmusing.blog.163.com/blog/static/1358349602010150224904/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: