状态模式的含义
状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。状态模式通过将每个状态封装到类中,并将行为委托到代表当前状态的对象,来使得单个对象在运行时能够动态改变行为。
核心思想及解释
状态模式的核心思想是状态封装。具体来说,状态模式把对象的行为封装在不同状态的对象中,对象的行为随着内部状态的改变而改变,状态改变时,对应的行为也会随之转移到另一种状态的实现上。这样,状态和行为使用不同的具体状态对象来表示,而不是通过多个条件判断语句来控制。
为什么要使用状态模式
- 减少条件分支:状态模式通过把复杂的状态逻辑分散到各个状态对象中,减少了条件语句的复杂性。
- 增强代码组织:每个状态可以被组织在独立的类中,提高了代码的模块化。
- 易于扩展:新增状态或改变状态的行为不需要修改主体类或其他状态类,符合开闭原则。
使用状态模式需要注意的点
- 状态过多时的管理问题:如果状态非常多,系统中会有大量状态类,可能会导致管理和维护的复杂度增加。
- 状态与状态机耦合:虽然状态模式减少了依赖,但状态逻辑和状态机之间依然存在耦合。
- 性能问题:每次状态转换可能涉及创建新的状态对象,如果状态转换非常频繁,可能会影响性能。
工程的应用场景
- 工作流处理:如文档审批流程,根据不同阶段改变处理行为。
- 游戏开发:游戏角色根据不同状态(如正常、受伤、加速等)改变行为。
- UI控件状态:UI控件(如按钮、菜单)根据不同状态(如激活、禁用、悬停)显示不同行为。
示例代码及解释
假设我们正在开发一个游戏中的玩家角色,该角色根据不同的健康状态(正常、受伤、严重受伤)改变其行为。
首先定义状态接口和具体状态类:
#include <iostream>
#include <string>
class Player;
class State
{
public:
virtual void handle(Player* player) = 0;
virtual ~State() {}
};
class NormalState : public State
{
public:
void handle(Player* player) override;
};
class InjuredState : public State
{
public:
void handle(Player* player) override;
};
class CriticalState : public State
{
public:
void handle(Player* player) override;
};
定义玩家类和状态改变逻辑:
class Player
{
State* currentState;
int health;
public:
Player() : currentState(new NormalState()), health(100) {}
~Player() { delete currentState; }
void setHealth(int h)
{
health = h;
if (health > 70)
{
changeState(new NormalState());
}
else if (health > 30)
{
changeState(new InjuredState());
}
else
{
changeState(new CriticalState());
}
}
void changeState(State* state)
{
delete currentState;
currentState = state;
currentState->handle(this);
}
void reportState()
{
currentState->handle(this);
}
};
void NormalState::handle(Player* player)
{
std::cout << "Player is in normal state." << std::endl;
}
void Injured
State::handle(Player* player)
{
std::cout << "Player is injured." << std::endl;
}
void CriticalState::handle(Player* player)
{
std::cout << "Player is in critical condition." << std::endl;
}
客户端代码:
int main()
{
Player player;
player.reportState(); // Initially normal
player.setHealth(50); // Change to injured state
player.reportState();
player.setHealth(20); // Change to critical state
player.reportState();
return 0;
}
输出代码运行结果
Player is in normal state.
Player is injured.
Player is injured.
Player is in critical condition.
Player is in critical condition.
这个示例演示了状态模式的应用,其中Player
类的行为根据其健康状态的改变而改变。State
类及其子类NormalState
, InjuredState
, CriticalState
定义了在不同状态下的具体行为。这样的设计使得添加新的状态或改变现有状态的行为变得简单,且不需要修改Player
类的内部实现。