23種設計模式之策略模式(c++實現)
定義
策略模式:定義了演算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。
Strategy 模式典型的結構圖為:
大家肯定看著很懵逼,其實第一次接觸類圖的時候我自己也是這樣。
那麼咱們舉個例子來解釋一下。
假設我們要實現一個角色遊戲,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()進行攻擊。