C++ 设计模式之状态模式
简介
1、状态模式 (State)是一种行为型设计模式,它允许一个对象在其内部状态发生改变时改变它的行为,对象看起来似乎修改了它的类。该模式主要用于实现一个对象在多种状态转换时能够自动切换到正确的行为。
2、状态模式 (State)应用场景包括但不限于:
2.1、当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时。
2.2、一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
3、状态模式 (State)的构成
3.1、状态基类
class State
{
public:virtual ~State() {}virtual void handleInput(CharacterContext& context, char input) = 0;virtual void update(CharacterContext& context) = 0;
};
3.2、具体状态类
class StandingState : public State
{
public:void handleInput(CharacterContext& context, char input);void update(CharacterContext& context);
};
4、状态模式 (State)的优点
4.1、封装性:状态的变更逻辑和动作执行封装在状态对象中,易于维护和扩展。
4.2、去除庞大的条件分支语句:状态模式通过把各种状态转移逻辑分布到状态对象中,去掉了原系统中对象的行为巨大且复杂的条件分支语句。
4.3、集中化状态管理:所有状态相关的代码都存在于某个State子类中,易于理解。
4.4、维护和扩展更简单:新增状态只需增加新的状态类,不需改变已有的状态类和上下文。
5、状态模式 (State)的缺点
5.1、类膨胀:如果状态很多,而且状态的逻辑也很复杂,就可能会产生很多的状态类,导致系统变得非常庞大。
5.2、依赖性:状态模式把各种状态对象的逻辑都分布在各个状态类中,每个状态类都依赖上下文对象,这增加了各个类之间的依赖性。
简单示例
1、定义
class State
{
public:virtual ~State() {}virtual void handleInput(CharacterContext& context, char input) = 0;virtual void update(CharacterContext& context) = 0;
};class StandingState : public State
{
public:void handleInput(CharacterContext& context, char input);void update(CharacterContext& context);
};class JumpingState : public State
{
public:void handleInput(CharacterContext& context, char input);void update(CharacterContext& context);
};class DuckingState : public State
{
public:void handleInput(CharacterContext& context, char input);void update(CharacterContext& context);
};class CharacterContext
{
public:CharacterContext(State* initialState);~CharacterContext();void handleInput(char input);void changeState(State* newState);void update();
private:State* currentState;
};
2、实现
void StandingState::handleInput(CharacterContext& context, char input)
{if (input == 'D'){context.changeState(new DuckingState());}else if (input == 'J'){context.changeState(new JumpingState());}
}void StandingState::update(CharacterContext& context)
{std::cout << "Character is standing." << std::endl;
}void JumpingState::handleInput(CharacterContext& context, char input)
{if (input == 'D'){context.changeState(new DuckingState());}
}void JumpingState::update(CharacterContext& context)
{std::cout << "Character is jumping." << std::endl;
}void DuckingState::handleInput(CharacterContext& context, char input)
{if (input == 'S'){context.changeState(new StandingState());}
}void DuckingState::update(CharacterContext& context)
{std::cout << "Character is ducking." << std::endl;
}CharacterContext::CharacterContext(State* initialState) : currentState(initialState)
{}CharacterContext::~CharacterContext()
{delete currentState;
}void CharacterContext::handleInput(char input)
{currentState->handleInput(*this, input);
}void CharacterContext::changeState(State* newState)
{delete currentState;currentState = newState;
}void CharacterContext::update()
{currentState->update(*this);
}
3、调用
CharacterContext character(new StandingState());
character.handleInput('D');
character.update();