策略模式的核心思路:将一个个算法分别封装来,使用算法的客户可以任意地替换任何一种算法。
策略模式最大的好处:当算法发生改变时,不会对算法的使用方式造成影响,也就是算法跟算法客户分别独立。
下面进行讲解:
场景:古代战争中,士兵对武器(大剑、长毛、弓箭)的选择就是一种策略模式,士兵可以自由选择自己擅长得武器进行战斗。
先看UML图:
实现此场景需要3个角色:
1、武器抽象,定义了Attck接口
2、具体的武器(大剑、长毛、弓箭),分别实现Attck接口
3、士兵,选择具体的武器,然后进行攻击
代码实现:
__interface IWeapon
{
public:
virtual void Attack() = 0;
};
class CSword:public IWeapon
{
public:
virtual void Attack() { cout << "大剑攻击!" << endl; }
};
class CSpear
{
public:
virtual void Attack() { cout << "长矛攻击!" << endl; }
};
class CArrow
{
public:
virtual void Attack() { cout << "弓箭射击!" << endl; }
};
class CSoldier
{
public:
void SetWeapon(IWeapon* wp) { m_pWeapon = wp; }
void Attack() { m_pWeapon->Attack(); }
private:
IWeapon* m_pWeapon;
};
客户端的调用颇为繁琐:
int main()
{
CSoldier joson;
IWeapon* pSword = new CSword();
joson.SetWeapon(pSword);//使用大剑
joson.Attack();
delete pSword;
IWeapon* pArrow = new CArrow();
joson.SetWeapon(pArrow);//使用弓箭
joson.Attack();
delete pArrow;
return 0;
}
与简单工厂模式结合:
为了避免客户端直接跟各种“策略”打交道,可以考虑与简单工厂模式结合使用:定义一个枚举类型,通过传递标签的方式让策略在策略上下文中创建。
武器类没有变化,这里只贴出士兵类和客户端的代码:
class CSoldier
{
public:
enum Weapon_Type{WEAPON_SWORD,WEAPON_SPEAR,WEAPON_ARROW};
CSoldier() { m_pWeapon = NULL; }
~CSoldier() { Release(); }
void SetWeapon(Weapon_Type eType) {
Release();
switch (eType)
{
case CSoldier::WEAPON_SWORD:
m_pWeapon = new CSword();
break;
case CSoldier::WEAPON_SPEAR:
m_pWeapon = new CSpear();
break;
case CSoldier::WEAPON_ARROW:
m_pWeapon = new CArrow();
break;
default:
break;
}
}
void Attack() { m_pWeapon->Attack(); }
void Release() {
if (m_pWeapon != NULL)
delete m_pWeapon;
}
private:
IWeapon* m_pWeapon;
};
int main()
{
CSoldier joson;
joson.SetWeapon(CSoldier::WEAPON_SPEAR);//使用长矛
joson.Attack();
joson.SetWeapon(CSoldier::WEAPON_SWORD);//使用大剑
joson.Attack();
joson.SetWeapon(CSoldier::WEAPON_ARROW);//使用弓箭
joson.Attack();
return 0;
}
最后,附上完整代码:
http://pan.baidu.com/s/1qXBYoHY