C++实现Behavioral - Strategy模式

也称为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类图:

 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中根本不存在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值