C++ 策略模式的具体案例与优缺点
Posted sanqima
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 策略模式的具体案例与优缺点相关的知识,希望对你有一定的参考价值。
策略模式:准备一组算法,并将每一个算法封装起来,使得它们可以互换。
1、策略模式中的角色与职责
在策略模式中分为4个角色:环境类Context、具体环境类SubContext、策略类Stategy、具体策略类SubStrategy。
- Context(环境类):环境类是一个抽象类,它通过属性成员m_pStrategy调用具体策略类里的函数,以实现不同功能。
- SubContext(具体环境类、子环境类):继承环境类Context,实现对某个对象或环境的描写。
- Strategy(策略类):是一个接口,里面有抽象的方法,这些抽象方法,需要SubStrategy去实现。
- SubStrategy(具体策略类、子策略类):实现抽象策略类里的算法,在运行时,覆盖Strategy父对象,实现对某个具体业务的处理。
如下:
Context环境类,是一个抽象类,它不仅仅可以代表上下左右的事物或场景,而且也可以代表某种生物,比如鸭子,它里面有3个函数:Flyed()、Quacked()、Display(),分别表示飞行、鸣叫、显示。鸭子分为很多种,有野鸭、红头鸭、道具鸭、模型鸭、橡皮鸭等,前2种有生命,后3种无生命,因此,野鸭、红头鸭、道具鸭等鸭属于子环境SubContext,鸭有翅膀,可以在水上飞、岸边飞、草场飞,这种飞行方式属于一种策略,因此放到Strategy接口里,然后再由具体策略类SubStrategy实现飞的方式。
鸭子的鸣叫,有的是呱呱叫、有的是吱吱叫、还有的是嘎嘎叫等等,所以鸣叫也是一种策略,需要用接口来封装,然后再用子策略去实现。
具体如下:
2、代码实现
2.1 飞行策略
//FlyBahavior.h
#pragma once
#include <iostream>
using namespace std;
//------------ 1) 飞行行为的接口 -----------------------//
class FlyBehavior
public:
virtual void Flyed() const = 0;
virtual ~FlyBehavior() = default;
;
class FlyNoWay : public FlyBehavior
public:
void Flyed() const override
cout << "I can't fly!" << endl;
;
class FlyRocketPowered :public FlyBehavior
public:
void Flyed() const override
cout << "I'm flying with a rocket" << endl;
;
class FlyWithWings :public FlyBehavior
public:
virtual void Flyed() const override
cout << "I'm flying" << endl;
;
2.2 鸣叫策略
//QuackBehavior.h
#pragma once
#include <iostream>
using namespace std;
//----------------- 2) 鸣叫行为的接口 -----------------//
class QuackBehavior
public:
virtual void Quacked() const = 0;
virtual ~QuackBehavior() = default;
;
class Quack :public QuackBehavior
public:
void Quacked() const override
cout << "Quack" << endl;
;
class MuteQuack :public QuackBehavior
public:
void Quacked() const override
cout << "Silence" << endl;
;
class Squeak : public QuackBehavior
public:
void Quacked() const override
cout << "Squeak" << endl;
;
2.3 鸭子类
//Duck.h
#pragma once
#include <iostream>
#include <memory>
#include "FlyBehavior.h"
#include "QuackBehavior.h"
using namespace std;
//--------------- 3) 鸭子类 --------------------//
class Duck
public:
std::unique_ptr<FlyBehavior> m_pFlyBehavior;
std::unique_ptr<QuackBehavior> m_pQuackBehavior;
Duck(std::unique_ptr<FlyBehavior> pFlyed, std::unique_ptr<QuackBehavior> pQuack)
:m_pFlyBehavior(std::move(pFlyed)), m_pQuackBehavior(std::move(pQuack))
;
virtual ~Duck() = default;
virtual void Display() const = 0;
void Quacked() const
m_pQuackBehavior->Quacked();
void Flyed() const
m_pFlyBehavior->Flyed();
void Swim() const
cout << "All ducks float,even decoys" << endl;
;
//--------------- 3.2) 道具鸭 --------------------//
class DecoyDuck :public Duck
public:
DecoyDuck()
:Duck(std::make_unique<FlyNoWay>(), std::make_unique<MuteQuack>())
void Display() const override
cout << "Decoy Duck" << endl;
;
//--------------- 3.3) 野鸭 --------------------//
class MallardDuck :public Duck
public:
MallardDuck()
:Duck(std::make_unique<FlyWithWings>(), std::make_unique<Quack>())
void Display() const override
cout << "Mallard Duck" << endl;
;
//--------------- 3.4) 模型鸭 --------------------//
class ModelDuck :public Duck
public:
ModelDuck()
: Duck(std::make_unique<FlyWithWings>(), std::make_unique<Quack>())
void Display() const override
cout << "Model Duck" << endl;
;
//--------------- 3.5) 红头鸭 --------------------//
class RedHeadDuck :public Duck
public:
RedHeadDuck()
:Duck(std::make_unique<FlyWithWings>(), std::make_unique<Quack>())
void Display() const override
cout << "Red Head Duck" << endl;
;
//--------------- 3.6) 橡皮鸭 --------------------//
class RubberDuck :public Duck
public:
RubberDuck()
: Duck(std::make_unique<FlyNoWay>(), std::make_unique<Squeak>())
void Display() const override
cout << "Rubber Duck" << endl;
;
2.4 主入口
//main.cpp
#include "FlyBehavior.h"
#include "QuackBehavior.h"
#include "Duck.h"
int main()
MallardDuck mallard;
mallard.Display();
mallard.Swim();
mallard.Quacked();
mallard.Flyed();
cout << "--------------- Mallard -----\\n" << endl;
RubberDuck rubberDuckie;
rubberDuckie.Display();
rubberDuckie.Swim();
rubberDuckie.Quacked();
rubberDuckie.Flyed();
system("pause");
return 0;
效果如下:
3、策略模式的优缺点
3.1 优点
- 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
- 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑,与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码(Hard Coding)在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。
- 策略模式提供了一种算法的复用机制。由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。
3.2 缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况,客户端的权限太大。
- 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类,会造成文件夹中class类个数的暴增。
以上是关于C++ 策略模式的具体案例与优缺点的主要内容,如果未能解决你的问题,请参考以下文章