Renbobo's Blog

Wo go where our vision is.

View project on GitHub

状态模式

29 Aug 2017

我们可以先看一个列子,某糖果机的操作如下图: {10}

箭头表示行为,圈表示状态,每个行为产生一个状态

行为:

  1. 投入硬币
  2. 转动把手
  3. 退回硬币
  4. 发放糖果(糖果机自动完成)

状态:

  1. 没有钱币
  2. 有钱币
  3. 售卖糖果
  4. 售罄

每一个状态由一个行为产生 每一个行为又受到当前状态的影响

状态可以有共同的行为,但是具体到每一个状态下,会有具体的反应。同时一个行为后,变为另一个状态。 类图:

回到刚才的例子,糖果机代码如下:

#include <iostream>

using namespace std;

enum MState{
    SOLD_OUT     = 0,//售罄
    NO_QUARTER   = 1,//没钱
    HAS_QUARTER  = 2,//有钱
    SOLD         = 3 //售卖中
};
//糖果机
class GumballMachine;
//状态基类
class State{
public:
    State(){
    }
    virtual ~State(){}
    virtual void insertQuarter(){
        cout << "You can't insert quarter" << endl;
    }
    virtual void ejectQuarter(){
        cout << "You haven't inserted a quarter" << endl;
    }
    virtual void turnCrank(){
        cout << "You turned, but there's no quarter" << endl;
    }
    virtual void dispense(){
        cout << "You need to pay first" << endl;
    }
    void printState(){
        cout << "State:" << m_name << endl;
    }

public:
    string m_name;
};
//无钱状态,等待用户投钱
class NoQuarterState : public State{
public:
    NoQuarterState(GumballMachine* gumballMachine){
        this->gumballMachine = gumballMachine;
        this->m_name = "NO_QUARTER";
    }
    virtual ~NoQuarterState(){}
    virtual void insertQuarter() {
        cout << "You inserted a quarter" << endl;
        gumballMachine->setHasQuraterState();
    }
public:
    GumballMachine* gumballMachine;
};
//有钱状态
class HasQuarterState : public State{
public:
    HasQuarterState(GumballMachine* gumballMachine){
        this->gumballMachine = gumballMachine;
        this->m_name = "HAS_QUARTER";
    }
    virtual ~HasQuarterState(){}
    virtual void ejectQuarter(){
        cout << "Quarter returned" << endl;
        gumballMachine->setNoquraterState();
    }
    virtual void turnCrank(){
        cout << "You turned .." << endl;
        gumballMachine->setSoldState();
    }
public:
    GumballMachine* gumballMachine;
};
//销售状态
class SoldState : public State{
public:
    SoldState(GumballMachine* gumballMachine){
        this->m_name = "SOLD";
        this->gumballMachine = gumballMachine;
    }
    virtual ~SoldState(){}
    virtual void dispense(){
        cout << "Out of Gumballs" << endl;
        gumballMachine->setNoquraterState();
    }
public:
    GumballMachine* gumballMachine;
};
//售罄状态
class SoldOutState : public State{
public:
    SoldOutState(GumballMachine* gumballMachine){
        this->m_name = "SOLD_OUT";
        this->gumballMachine = gumballMachine;
    }
    virtual ~SoldOutState(){}
    virtual void insertQuarter(){
        printword();
    }
    virtual void ejectQuarter(){
        printword();
    }
    virtual void turnCrank(){
        printword();
    }
    virtual void dispense() {
        printword();
    }
    void printword(){
        cout << "The GumballMachine* has sold out" << endl;
    }
public:
    GumballMachine* gumballMachine;
};
//糖果机
class GumballMachine{
public:
    GumballMachine(int count = 0){
        this->m_count = count;
        m_SoldOutState = new SoldOutState(this);
        m_HasQuraterState = new HasQuarterState(this);
        m_NoQuraterState = new NoQuarterState(this);
        m_SoldState = new SoldState(this);
        if(this->m_count == 0)
            this->m_State = m_SoldOutState;
        else
            this->m_State = m_NoQuraterState;
    }
    ~GumballMachine(){}
    void setSoldOutState(){
        m_State=m_SoldOutState;
    }
    void setSoldState(){
        m_State=m_SoldState;
    }
    void setNoquraterState(){
        m_State=m_NoQuraterState;
    }
    void setHasQuraterState(){
        m_State=m_HasQuraterState;
    }
    void insertQuarter(){
        m_State->insertQuarter();
    }
    void ejectQuarter(){
        m_State->ejectQuarter();
    }
    void turnCrank(){
        m_State->turnCrank();
    }
    void dispense() {
        m_State->dispense();
    }
    void getState(){
        m_State->printState();
    }
public:
    int m_count;
    State* m_State;
    State* m_SoldOutState;
    State* m_SoldState;
    State* m_HasQuraterState;
    State* m_NoQuraterState;
};

int main(){
    GumballMachine* gumballMachine;
    gumballMachine->insertQuarter();
    return 1;
}