欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

状态模式

程序员文章站 2022-06-17 17:06:27
...

简介

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

  • 设计模式中的行为模式。

主要解决的问题

  • 当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

角色

  • Context(环境类):拥有状态对象,充当状态管理器的角色,在Context类中对状态进行改变。

  • State(抽象状态类):接口。具体状态类的抽象。环境类存在多个状态,不同的状态对应不同的行为。

  • ConcreteState(具体状态类):将不同对象下的行为封装到具体状态类中,使得环境类对象在其内部状态改变时可以改变它的行为,给客户端一种改变类的错觉。

图解

状态模式

优点

  • 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。

  • 允许状态转换逻辑与状态对象合为一体,而不是提供一个巨大的条件语句块,可以避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。

缺点

  • 会增加系统中类和对象的个数,导致系统运行开销增大。

  • 结构与实现较为复杂,如果使用不当将导致程序结构和代码混乱,增加系统设计的难度。

  • 增加新的状态时,需要增加新的状态类,修改状态转换代码,否则无法转换到新状态;而且修改某个状态类的行为也需要修改对应的源代码。不符合“开闭”原则。

应用场景

  • 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。(对象的行为依赖于它的状态,状态的改变导致行为的变化。)

  • 一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。复杂的条件语句会使代码的可维护性和灵活性变差,不能方便的删除和增加状态。

实例

  • 游戏是广大青少年休闲娱乐的首选项。通常我们玩LOL无非处于以下状态:

    • 登录游戏,好戏就要上演
    • 设置角色,选择吊炸天的角色,使敌人一击致命
    • 开始游戏,是时候展现真正的技术了
    • 攻破敌人阵营,游戏结束
    • 退出游戏,去食堂犒劳自己的胃
  • context.h

#ifndef _CONTEXT_H_
#define _CONTEXT_H_

class Game{
public:
    ~Game(){
        if(state!=nullptr){
            delete state;
            state = nullptr;
        }
    }
    Game(State *state):state(state) {}
    void setState(State* state) {
        this->state = state; 
    }
    void Request() { 
        state->Handle(this);
    }
private:
    State *state;
};

#endif // _CONTEXT_H_
  • state.h
#ifndef _STATE_H_
#define _STATE_H_

class Game;

class State{
public:
    virtual void Handle(Game *game) = 0;
};

#endif // _STATE_H_
  • concrete_state.h
#ifndef _CONCRETE_STATE_H_
#define _CONCRETE_STATE_H_

#include "state.h"
#include "context.h"
#include<iostream>

using namespace std;

class ExitState : public State {
public:
    void Handle(Game *game) {
        cout << "exit game..." << endl;
    }
};

class EndState : public State {
public:
    void Handle(Game *game) {
        cout << "exit game..." << endl;
        game->setState(new ExitState());
    }
};

class StartState : public State {
public:
    void Handle(Game *game) {
        cout << "start game..." << endl;
        game->setState(new EndState());
    }
};

class SetState : public State{
public:
    void Handle(Game *game) {
        cout << "set game..." << endl;
        game->setState(new StartState());
    }
};

class LogState : public State {
public:
    void Handle(Game *game) {
        cout << "log game..." << endl;
        game->setState(new SetState());
    }
};

#endif // _CONCRETE_STATE_H_
  • main.cpp
#include<iostream>
#include"concrete_state.h"

using namespace std;

int main(int argc, char* argv[]) {
    State *state = new LogState();
    Game *game = new Game(state);
    for (int i = 0; i < 5; ++i) {
        game->Request();
    }
    getchar();
    return 0;
}
  • 运行结果
    状态模式
相关标签: 状态模式