1. 程式人生 > >23種設計模式之策略模式(c++實現)

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()進行攻擊。