23种设计模式之策略模式(c++实现)

定义

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
Strategy 模式典型的结构图为:
UML
大家肯定看着很懵逼,其实第一次接触类图的时候我自己也是这样。
那么咱们举个例子来解释一下。
假设我们要实现一个角色游戏,context为所有角色的基类(例子的代码后面会实现,此处只是拿context举例,此处的context并不是基类),一个角色可以切换不同的武器。然后strategy则为不同的武器的基类,而不同的武器的攻击方式是不同的,斧头的攻击为砍,剑的攻击为刺,弓箭的话为射击。乍一看感觉好麻烦啊。难不成得给一个角色类把所有的武器类都包含进去,然后切换武器的时候删除掉之前的武器,然后再重新开辟一个新的武器类。这样子的话给我们设计会带来非常大的不方便。而且假如我们有了新的武器,比如魔法棒,那么我们不是应该给角色类里面再添加魔法棒类,这样的话会让角色类变得非常庞大,而且非常不利于后期的维护,我们不能每增加一个武器就给角色类添加一个武器类吧。所以我们在设计的时候要让系统不去担心任何改变(武器的添加与更改),此时策略模式将会是一个不错的选择。
首先咱们先根据类图实现一下代码。关于武器的代码咱们后面实现。

代码

context.h

#ifndef STRATEGY_CONTEXT_H
#define STRATEGY_CONTEXT_H

#include "context.h"
#include "strategy.h"
#include <iostream>
using namespace std;

class Context
{
public:
    Context(Strategy* stg);
    ~Context();
    void DoAction();

protected:
    Strategy* _stg;
};

Context::Context(Strategy* stg)
{
    _stg = stg;
}

Context::~Context()
{
    if(!_stg)
        delete _stg;
}

void Context::DoAction()
{
    _stg->AlgrithmInterface();
}

#endif //STRATEGY_CONTEXT_H

strategy.h

#include "strategy.h"
#include <iostream>
using namespace std;

class Strategy
{
public:
    Strategy();
    virtual ~Strategy();
    virtual void AlgrithmInterface() = 0;
};

class ConcreteStrategyA : public Strategy
{
public:
    ConcreteStrategyA();
    virtual ~ConcreteStrategyA();
    void AlgrithmInterface();
};

class ConcreteStrategyB : public Strategy
{
public:
    ConcreteStrategyB();
    virtual ~ConcreteStrategyB();
    void AlgrithmInterface();
};

Strategy::Strategy()
{

}

Strategy::~Strategy()
{
    cout << "~Strategy....." << endl;
}


ConcreteStrategyA::ConcreteStrategyA()
{
    cout << "test ConcreteStrategyA......" << endl;
}

ConcreteStrategyA::~ConcreteStrategyA()
{
    cout << "~test ConcreteStrategyA......" << endl;
}

void ConcreteStrategyA::AlgrithmInterface() {
    cout << "GUA GUA" << endl;
}

ConcreteStrategyB::ConcreteStrategyB()
{
    cout << "test ConcreteStrategyB......" << endl;
}

ConcreteStrategyB::~ConcreteStrategyB()
{
    cout << "~test ConcreteStrategyB......" << endl;
}

void ConcreteStrategyB::AlgrithmInterface()
{
    cout << "test ConcreteStrategyB......" << endl;
}

main.cpp

#include "context.h"
#include "strategy.h"
#include <iostream>
using namespace std;

int main()
{
    Strategy* ps = new ConcreteStrategyA();

    Context* pc = new Context(ps);

    pc->DoAction();

    if(pc != NULL)
    {
        delete pc;
    }
    return 0;

}

这里面Strategy为虚基类,具体的策略继承自Strategy,而在Context中有一个Strategy的指针,该指针可以指向Strategy的所有子类,又因为Strategy中的AlgrithmInterface为虚函数,根据多态,Strategy指针调用AlgrithmInterface调用的实际是子类的AlgrithmInterface函数。这样的话Context中只需要一个Strategy成员即可调用任何Strategy的子类。

策略模式的应用

下面我们来将上面的角色和武器的例子进行代码的实现,从而更好的理解策略模式。
这里写图片描述
main.cpp

#include <iostream>
#include "Character.h"
#include "Weapon.h"
using std::cout;
using std::endl;

int main()
{
    Character** characters = new Character*[3];
    Weapon** weapons = new Weapon*[4];
    characters[0] = new King();
    characters[1] = new Queen();
    characters[2] = new Knight();

    weapons[0] = new Sword();
    weapons[1] = new Knife();
    weapons[2] = new Axe();
    weapons[3] = new BowAndArrow();

    characters[0]->setWeapon(weapons[0]);
    characters[1]->setWeapon(weapons[1]);
    characters[2]->setWeapon(weapons[2]);

    for(int i = 0; i < 3; ++i)
    {
        characters[i]->fight();
    }

    characters[2]->setWeapon(weapons[3]);
    characters[2]->fight();
    delete[] characters;
    delete[] weapons;
}

Weapon.h

#ifndef STRATEGY_TEST_WEAPON_H
#define STRATEGY_TEST_WEAPON_H

#include <iostream>
using std::cout;
using std::endl;

class Weapon
{
public:
    Weapon()
    {}
    virtual ~Weapon() {}
    virtual void useWeapon() = 0;
};

class Sword : public Weapon
{
    void useWeapon()
    {
        cout << "宝剑挥舞" << endl;
    }
};

class Knife : public Weapon
{
    void useWeapon()
    {
        cout << "匕首刺杀" << endl;
    }
};

class Axe : public Weapon
{
    void useWeapon()
    {
        cout << "斧头劈砍" << endl;
    }
};

class BowAndArrow : public Weapon
{
    void useWeapon()
    {
        cout << "弓箭射击" << endl;
    }
};

#endif //STRATEGY_TEST_WEAPON_H

Character.h

#ifndef STRATEGY_TEST_CHARACTER_H
#define STRATEGY_TEST_CHARACTER_H

#include "Weapon.h"

class Character
{
protected:
    Weapon* weapon;
public:
    Character()
    {
        this->weapon = nullptr;
    }
    virtual ~Character() {}
    void setWeapon(Weapon* weapon)
    {
        this->weapon=weapon;
    }
    virtual void fight() = 0;
};

class King : public Character  //国王类
{
    void fight()
    {
        this->weapon->useWeapon();
    }
};

class Queen : public Character  //皇后类
{
    void fight()
    {
        this->weapon->useWeapon();
    }
};

class Knight : public Character  //骑士类
{
    void fight()
    {
        this->weapon->useWeapon();
    }
};

#endif //STRATEGY_TEST_CHARACTER_H

Character(角色)为抽象类,由具体的角色(King, Queen, Knight)来继承。
Weapon(武器)也属于抽象类,由具体的武器(Sword, Knife, BowAndArrow, Axe)来继承。
换武器的话可以调用setWeapon(),战斗过程(fight)中可以调用useWeapon()进行攻击。

猜你喜欢

转载自blog.csdn.net/Sanjiye/article/details/80779260