状态模式(State)

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类.

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

要点:
1.状态模式允许一个对象基于内部状态而拥有不同的行为
2.和程序状态机(PSM)不同,状态模式用类代表状态
3.Context会将行为委托给当前状态对象
4.通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了
5.状态模式和策略模式有相同的类图,但它们的意图不同
6.策略模式通常会用行为或算法来配置Context类
7.状态模式允许Context随着状态的改变而改变行为
8.状态转换可以由State类或Context类控制
9.使用状态模式通常会导致设计中类的数目大量增加//确实如此...
10.状态类可以被多个Context实例共享

状态模式(State)_第1张图片

由于2个类的相互引用,导致很多类都要写进cpp,代码虽然比较多,但逻辑并不复杂
GameState.h
#ifndef GAMESTATE_H
#define GAMESTATE_H

enum State{
    ADDCOINS,
    PLAYGAME,
    BADGAME,
    GOODGAME,
    GAMEOVER
};

class GameState{
public:
    virtual void addCoins()=0;
    virtual void playGame()=0;
    virtual void badGame()=0;
    virtual void goodGame()=0;
    virtual void gameOver()=0;
};

#endif // GAMESTATE_H



AddCoinsState.h
#ifndef ADDCOINSSTATE_H
#define ADDCOINSSTATE_H
#include "GameState.h"
#include "GameMachine.h"
#include <iostream>
using namespace std;

class GameMachine;
class AddCoinsState:public GameState{
private:
    GameMachine* mMachine;
public:
    AddCoinsState(GameMachine* machine);
    void addCoins();
    void playGame();
    void badGame();
    void goodGame();
    void gameOver();
};

#endif // ADDCOINSSTATE_H


AddCoinsState.cpp
#include "AddCoinsState.h"

AddCoinsState::AddCoinsState(GameMachine *machine){
    mMachine = machine;
}

void AddCoinsState::addCoins(){
    mMachine->setCount(mMachine->getCount()+2);
    cout << "add a coin" << endl;
    mMachine->setState(mMachine->getPlayGameState());
}

void AddCoinsState::playGame(){
    cout << "please add a coin" << endl;
}

void AddCoinsState::badGame(){
    cout << "no coin" << endl;
}

void AddCoinsState::goodGame(){
    cout << "no coin" << endl;
}

void AddCoinsState::gameOver(){
    cout << "no coin" << endl;
}



PlayGameState.h
#ifndef PLAYGAMESTATE_H
#define PLAYGAMESTATE_H
#include "GameState.h"
#include "GameMachine.h"

class GameMachine;
class PlayGameState:public GameState{
private:
    GameMachine* mMachine;
    bool mFlag;
public:
    PlayGameState(GameMachine* machine);
    void addCoins();
    void playGame();
    void badGame();
    void goodGame();
    void gameOver();
};

#endif // PLAYGAMESTATE_H



PlayGameState.cpp
#include "PlayGameState.h"
#include <stdlib.h>

PlayGameState::PlayGameState(GameMachine *machine){
    mMachine = machine;
    mFlag = false;
}

void PlayGameState::addCoins(){
    mMachine->setCount(mMachine->getCount()+2);
}

void PlayGameState::playGame(){
    srand(time(0));
    while(mMachine->getCount()>0){
        if(not mFlag){
            int game = rand()%10+1;//1-10
            if(game>=8){
                mFlag = true;//只给一次good game的机会
                mMachine->setState(mMachine->getGoodGameState());
                mMachine->goodGame();
            }
        }
        mMachine->setState(mMachine->getBadGameState());
        mMachine->badGame();
    }
    mMachine->setState(mMachine->getGameOverState());
    mMachine->gameOver();
}

void PlayGameState::badGame(){
    cout << "playing" << endl;
}

void PlayGameState::goodGame(){
    cout << "playing" << endl;
}

void PlayGameState::gameOver(){
    cout << "playing" << endl;
}



BadGameState.h
#ifndef BADGAMESTATE_H
#define BADGAMESTATE_H
#include "GameState.h"
#include "GameMachine.h"

class GameMachine;
class BadGameState:public GameState{
private:
    GameMachine* mMachine;
public:
    BadGameState(GameMachine* machine);
    void addCoins();
    void playGame();
    void badGame();
    void goodGame();
    void gameOver();
};
#endif // BADGAMESTATE_H


BadGameState.cpp
#include "BadGameState.h"

BadGameState::BadGameState(GameMachine *machine){
    mMachine = machine;
}

void BadGameState::addCoins(){
    mMachine->setCount(mMachine->getCount()+2);
}

void BadGameState::playGame(){
    badGame();
}

void BadGameState::badGame(){
    mMachine->setState(mMachine->getPlayGameState());
    mMachine->setCount(mMachine->getCount()-1);
    cout << "a bad game,coin-1:" << mMachine->getCount() << endl;
}

void BadGameState::goodGame(){
    badGame();
}

void BadGameState::gameOver(){
    badGame();
}



GoodGameState.h
#ifndef GOODGAMESTATE_H
#define GOODGAMESTATE_H
#include "GameState.h"
#include "GameMachine.h"

class GameMachine;
class GoodGameState:public GameState{
private:
    GameMachine* mMachine;
public:
    GoodGameState(GameMachine* machine);
    void addCoins();
    void playGame();
    void badGame();
    void goodGame();
    void gameOver();
};
#endif // GOODGAMESTATE_H



GoodGameState.cpp
#include "GoodGameState.h"

GoodGameState::GoodGameState(GameMachine *machine){
    mMachine = machine;
}

void GoodGameState::addCoins(){
    mMachine->setCount(mMachine->getCount()+2);
}

void GoodGameState::playGame(){
    goodGame();
}

void GoodGameState::badGame(){
    goodGame();
}

void GoodGameState::goodGame(){
    mMachine->setState(mMachine->getPlayGameState());
    mMachine->setCount(mMachine->getCount()+1);
    cout << "a good game,coin+1:" << mMachine->getCount() << endl;
}

void GoodGameState::gameOver(){
    goodGame();
}



GameOverState.h
#ifndef GAMEOVERSTATE_H
#define GAMEOVERSTATE_H
#include "GameState.h"
#include "GameMachine.h"

class GameMachine;
class GameOverState:public GameState{
private:
    GameMachine* mMachine;
public:
    GameOverState(GameMachine* machine);
    void addCoins();
    void playGame();
    void badGame();
    void goodGame();
    void gameOver();
};
#endif // GAMEOVERSTATE_H



GameOverState.cpp
#include"GameOverState.h"

GameOverState::GameOverState(GameMachine* machine){
    mMachine = machine;
}
void GameOverState::addCoins(){
    mMachine->setCount(mMachine->getCount()+2);
}
void GameOverState::playGame(){
    gameOver();
}
void GameOverState::badGame(){
    gameOver();
}
void GameOverState::goodGame(){
    gameOver();
}
void GameOverState::gameOver(){
    cout << "game over!" << endl;
}



GameMachine.h
#ifndef GAMEMACHINE_H
#define GAMEMACHINE_H
#include "GameState.h"
#include "AddCoinsState.h"
#include "PlayGameState.h"
#include "BadGameState.h"
#include "GoodGameState.h"
#include "GameOverState.h"
#include <assert.h>
#include <iostream>
using namespace std;

class GameMachine{
private:
    State mState;
    int mCount;
    GameState* addCoinsState;
    GameState* playGameState;
    GameState* badGameState;
    GameState* goodGameState;
    GameState* gameOverState;
    GameState* gameState;//default
public:
    GameMachine(int count);
    void addCoins(){
        gameState->addCoins();
        cout << "add a coins:" << mCount << endl;
    }
    void playGame(){
        gameState->playGame();
    }
    void badGame(){
        gameState->badGame();
    }
    void goodGame(){
        gameState->goodGame();
    }
    void gameOver(){
        gameState->gameOver();
    }
    void setState(GameState* state){
        gameState = state;
    }
    int getCount()const{
        return mCount;
    }
    void setCount(int count){
        mCount = count;
    }
    GameState* getAddCoinsState(){
        return addCoinsState;
    }
    GameState* getPlayGameState(){
        return playGameState;
    }
    GameState* getBadGameState(){
        return badGameState;
    }
    GameState* getGoodGameState(){
        return goodGameState;
    }
    GameState* getGameOverState(){
        return gameOverState;
    }
};

#endif // GAMEMACHINE_H



GameMachine.cpp
#include "GameMachine.h"

GameMachine::GameMachine(int count){
    assert(count>=0);
    cout << "add " << count << " coins" << endl;
    mCount = count;
    addCoinsState = new AddCoinsState(this);
    playGameState = new PlayGameState(this);
    badGameState = new BadGameState(this);
    goodGameState = new GoodGameState(this);
    gameOverState = new GameOverState(this);
    if(count>0){
        mState = PLAYGAME;
        gameState = new PlayGameState(this);
    }else{
        mState = GAMEOVER;
        gameState = new GameOverState(this);
    }
}



main.cpp
#include "GameMachine.h"

int main(){
    GameMachine *machine = new GameMachine(5);
    machine->addCoins();
    machine->playGame();
}



add 5 coins
add a coins:7//投一个币加2次机会
a bad game,coin-1:6
a good game,coin+1:7
a bad game,coin-1:6
a bad game,coin-1:5
a bad game,coin-1:4
a bad game,coin-1:3
a bad game,coin-1:2
a bad game,coin-1:1
a bad game,coin-1:0
game over!


一份关于rtsp的实现
#include <iostream>
using namespace std;

class RTSPState
{
public:
    RTSPState(){}
    virtual ~RTSPState(){}
    virtual bool processDescribe()
    {
        cout << "无法处理describe" << endl;
        return false;
    }
    virtual bool processSetup()
    {
        cout << "无法处理setup" << endl;
        return false;
    }
    virtual bool processPlay()
    {
        cout << "无法处理play" << endl;
        return false;
    }
    virtual bool processTeardown()
    {
        cout << "无法处理teardown" << endl;
        return false;
    }
};

class DescribeState:public RTSPState
{
public:
    bool processSetup()
    {
        cout << "处理setup" << endl;
        return true;
    }
};

class SetupState:public RTSPState
{
public:
    bool processPlay()
    {
        cout << "处理play" << endl;
        return true;
    }
};

class PlayState:public RTSPState
{
public:
    bool processTeardown()
    {
        cout << "处理teardown" << endl;
        return true;
    }
};

class TeardownState:public RTSPState
{
public:
    bool processDescribe()
    {
        cout << "处理describe" << endl;
        return true;
    }
};

class RTSPLink
{
public:
    RTSPLink()
    {
        mDescribeState = new DescribeState;
        mSetupState = new SetupState;
        mPlayState = new PlayState;
        mTeardownState = new TeardownState;
        mRtspState = mTeardownState;
    }

    ~RTSPLink()
    {
        mRtspState = NULL;
        if(mDescribeState!=NULL)
        {
            delete mDescribeState;
            mDescribeState = NULL;
        }
        if(mSetupState!=NULL)
        {
            delete mSetupState;
            mSetupState = NULL;
        }
        if(mPlayState!=NULL)
        {
            delete mPlayState;
            mPlayState = NULL;
        }
        if(mTeardownState!=NULL)
        {
            delete mTeardownState;
            mTeardownState = NULL;
        }
    }

    void setState(RTSPState* rtspState)
    {
        mRtspState= rtspState;
    }

    RTSPState* getDescribeState()
    {
        return mDescribeState;
    }

    RTSPState* getSetupState()
    {
        return mSetupState;
    }

    RTSPState* getPlayState()
    {
        return mPlayState;
    }

    RTSPState* getTeardownState()
    {
        return mTeardownState;
    }

    bool processDescribe()
    {
        if(mRtspState->processDescribe())
        {
            setState(mDescribeState);
            return true;
        }
        setState(mTeardownState);
        return false;
    }

    bool processSetup()
    {
        if(mRtspState->processSetup())
        {
            setState(mSetupState);
            return true;
        }
        setState(mTeardownState);
        return false;
    }

    bool processPlay()
    {
        if(mRtspState->processPlay())
        {
            setState(mPlayState);
            return true;
        }
        setState(mTeardownState);
        return false;
    }

    bool processTeardown()
    {
        if(mRtspState->processTeardown())
        {
            setState(mTeardownState);
            return true;
        }
        setState(mTeardownState);
        return false;
    }

private:
    RTSPState *mDescribeState;

    RTSPState *mSetupState;

    RTSPState *mPlayState;

    RTSPState *mTeardownState;

    RTSPState *mRtspState;
};

int main()
{
    RTSPLink * rtspLink = new RTSPLink;
    rtspLink->processDescribe();
    rtspLink->processSetup();
    rtspLink->processPlay();
    rtspLink->processTeardown();
    cout << "设置playstate" << endl;
    rtspLink->setState(rtspLink->getPlayState());
    rtspLink->processDescribe();
}

处理describe
处理setup
处理play
处理teardown
设置playstate
无法处理describe

你可能感兴趣的:(状态模式)