C++ 策略模式 - 来一场说走就走的旅行

高效程序员

共 1350字,需浏览 3分钟

 ·

2020-09-27 05:41

策略模式(Strategy Pattern)定义了一系列算法,把它们一个个封装起来,并且使其可以互相替换。Strategy 可以使算法独立于使用算法的客户端。



1

模式结构


UML 结构图:




  • Context(环境角色):持有一个对 Strategy 的引用,最终给客户端调用。

  • Strategy(抽象策略):定义了一个公共接口,让不同的算法以不同的方式来实现。通过这个接口,Context 可以调用不同的算法。

  • ConcreteStrategy(具体策略):实现 Strategy 定义的接口,提供具体算法的实现。



2

优缺点



优点:


  • 各自使用封装的算法,可以很容易地引入新的算法来满足相同的接口。

  • 由于实现的是同一个接口,所以策略之间可以自由切换。

  • Strategy 使客户端能够选择所需的算法,而无需使用 switch/case 或 if/else 语句。

  • 算法的细节完全封装在 Strategy 类中,因此,可以在不影响 Context 类的情况下更改算法的实现。



缺点:


  • 客户端必须知道所有的策略,了解它们之间的区别,以便适时选择恰当的算法。

  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。



3

适用场景


  • 多个类有不同的表现形式,每种表现形式可以独立成单独的算法。

  • 需要在不同情况下使用不同的算法,以后算法可能还会增加。

  • 对客户端隐藏具体算法的实现细节,彼此完全独立。



4

案例分析




说走就走的旅行 - 出行方式





每天,我们做着同样的工作,遇见同样的人,吃着同样的食物 ...... 日复一日,年复一年!当生活陷入重复,想遇到新鲜的人,新鲜的事,为苍白的生活添加一些色彩,何不来一场说走就走的旅行!


要出去玩,有很多种出行方式,比如:自行车、公交、自驾、火车、飞机等,如何选择最合适的呢?


  • 如果离家近,又怕堵车,可以骑自行车。

  • 如果离家远,但想省钱,早点出发,可以乘公交车。

  • 如果有车,并且不介意支付停车费,可以选择自驾。

  • 如果没有车,但赶时间,可以乘出租车。

  • …...


这里的每一种出行方式都是一种具体的策略,至于如何选择,需要基于成本、便利和时间之间的权衡。



5

代码实现



创建抽象策略


抽象策略由交通工具表示,它包含了一个 Run() 接口,用于提供出行方式:


// strategy.h
#ifndef STRATEGY_H
#define STRATEGY_H

// 出行策略
class ITransport
{

public:
    virtual ~ITransport() {}
    virtual void Run() 0;
};

#endif // STRATEGY_H



创建具体策略


具体的出行策略有很多种,像自行车、汽车、火车:


// concrete_strategy.h
#include "strategy.h"
#include 

// 自行车
class Bike : public ITransport
{
public:
    void Run() override 
        std::cout << "By bike" << std::endl;
    }
};

// 汽车
class Car : public ITransport
{
public:
    void Run() override 
        std::cout << "By car" << std::endl;
    }
};

// 火车
class Train : public ITransport
{
public:
    void Run() override {
        std::cout << "By train" << std::endl;
    }
};

#endif // CONCRETE_STRATEGY_H



创建环境角色


在这里,可以将环境角色理解为旅行者,它可以选择具体的出行工具。而根据工具的不同,出行方式也有所不同(在内部,Trave() 最终调用的是 ITransport 的相应方法):


// context.h
#ifndef CONTEXT_H
#define CONTEXT_H

#include "strategy.h"

// 旅行者
class Tourists
{

public:
    Tourists(ITransport *transport) { 
        m_pTransport = transport;
    }

    void Travel() {
        if (nullptr != m_pTransport)
            m_pTransport->Run(); 
    }

private:
    ITransport *m_pTransport = nullptr;
};

#endif // CONTEXT_H



创建客户端


旅程开始,尽情享受吧:


注意:策略之间可以相互替换,比如张三可以骑自行车,也可以开车,或者是坐火车,其他人也一样。


// main.cpp
#include "context.h"
#include "concrete_strategy.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete p; p=nullptr;} }
#endif

int main()
{
    ITransport *bike = new Bike();
    ITransport *car = new Car();
    ITransport *train = new Train();

    // 张三骑自行车、李四开车、王五坐火车
    Tourists *zhangsan = new Tourists(bike);
    Tourists *lisi = new Tourists(car);
    Tourists *wangwu = new Tourists(train);

    zhangsan->Travel();
    lisi->Travel();
    wangwu->Travel();

    SAFE_DELETE(bike);
    SAFE_DELETE(car);
    SAFE_DELETE(train);

    SAFE_DELETE(zhangsan);
    SAFE_DELETE(lisi);
    SAFE_DELETE(wangwu);

    getchar();

    return 0;
}


输出如下:

By bike

By car

By train


·END·

浏览 92
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报