设计模式之策略设计模式
一、状态设计模式概念
策略模式(Strategy) 是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
适用场景
- 当你想使用对象中各种不同的算法变体, 并希望能在运行时切换算法时, 可使用策略模式。
- 当你有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式。
- 如果算法在上下文的逻辑中不是特别重要, 使用该模式能将类的业务逻辑与其算法实现细节隔离开来。
- 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时, 可使用该模式。
状态设计模式的结构:
- 上下文 (Context) 维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。
- 策略 (Strategy) 接口是所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法。
- 具体策略 (Concrete Strategies) 实现了上下文所用算法的各种不同变体。
- 当上下文需要运行算法时, 它会在其已连接的策略对象上调用执行方法。 上下文不清楚其所涉及的策略类型与算法的执行方式。
- 客户端 (Client) 会创建一个特定策略对象并将其传递给上下文。 上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。
代码如下:
问题:做一款打斗游戏,玩家使用的英雄使用不同的武器将会产生不同的损伤效果。
解决方案:定义一些列的算法,把他们一个个封装起来,并且使它们可以相互替换。本模式使得算法可以独立于使用它的客户而变化。
#include <iostream>
#include <string>
class Weapon
{
public:
virtual std::string fightAlgorithm() const = 0;
};
class Nife: public Weapon
{
public:
std::string fightAlgorithm() const override
{
return "nife";
}
};
class Axe : public Weapon
{
public:
std::string fightAlgorithm() const override
{
return "Axe";
}
};
//context
class Hero
{
private:
Weapon* m_weapon;
public:
Hero(Weapon* weapon=nullptr) : m_weapon(weapon)
{
}
void setWeapon(Weapon* weapon)
{
m_weapon = weapon;
}
void fight()
{
std::cout << m_weapon->fightAlgorithm() << std::endl;
}
};
int main()
{
std::cout<<"客户端:nife攻击"<<std::endl;
Nife nife;
Hero hero1(&nife);
hero1.fight();
std::cout<<"客户端:Axe攻击"<<std::endl;
Axe axe;
hero1.setWeapon(&axe);
hero1.fight();
return 0;
}
二、与其他模式的关系
- 桥接模式 (opens new window)、 状态模式 (opens new window)和策略模式 (opens new window)(在某种程度上包括适配器模式 (opens new window)) 模式的接口非常相似。 实际上, 它们都基于组合模式 (opens new window)——即将工作委派给其他对象, 不过也各自解决了不同的问题。 模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。
- 状态 (opens new window)可被视为策略 (opens new window)的扩展。 两者都基于组合机制: 它们都通过将部分工作委派给 “帮手” 对象来改变其在不同情景下的行为。 策略使得这些对象相互之间完全独立, 它们不知道其他对象的存在。 但状态模式没有限制具体状态之间的依赖, 且允许它们自行改变在不同情景下的状态。