状态模式

来源:互联网 发布:程序员桌子 编辑:程序博客网 时间:2024/05/08 11:09
  1. 定义一个State接口。在接口内,糖果机每个动作对应一个方法。
  2. 为机器中的每个状态实现状态类。这些类负责在对应的状态下进行机器的行为。
  3. 将动作委托到状态类。
    这里写图片描述
状态 描述 NoQuarterState 机器内有糖果,还没投入25分硬币 HasQuarterState 投入25分硬币,进入SoldState SoldState 发放糖果,总数<0进入SoldOutState,否则进入NoQuarterState SoldOutState 显示”糖果售罄“

①没有投入硬币状态

class NoQuarterState : public State{    GumballMachine * gumballMachine;public:    NoQuarterState(GumballMachine *gumballMachine){        this->gumballMachine = gumballMachine;    }    void insertQuarter(){        cout << "You inserted a quarter" << endl;        gumballMachine->setState(gumballMachine->getHasQuarterState());    }    void ejectQuarter(){ cout<<"You haven't inserted a quarter"<<endl;}    void tunCrank(){cout << "You turned, but there's no quarter"<<endl;}    // 不恰当动作    void despense(){cout << "You need to pay first"<<endl;}};

②投入硬币状态

class HasQuarterState : public State{    GumballMachine * gumballMachine;public:    HasQuarterState (GumballMachine * gumballMachine){        this->gumballMachine = gumballMachine;    }    void insertQuarter(){         //  与没有投入硬币不同        cout << "You cannot inserted another quarter" << endl;    }    void ejectQuarter(){         cout<<"Quarter returned..."<<endl;        gumballMachine->setState(gumballMachine->getNoQuarterState());    }    void tunCrank(){        cout << "You turned"<<endl;        gumballMachine->setState(gumballMachine->getSoldState())    }       void despense(){cout << "You need to pay first"<<endl;}     // 不恰当动作};

将每个状态局部化到自己的类中;对修改关闭,对扩展开放—-可以加入新的类。防止大块的if..else 语句出现。

糖果机:

class GumballMachine{    State * noQuarterState;           // 状态对象    State * hasQuarterState;    State * soldState;    State * soldOutState;    State * state ;    int count = 0;                   // 当前糖果数目为0;public:    GumballMachine(int numberGumballs):state(soldOutState)  {    State * noQuarterState = new noQuarterState(this);    State * hasQuarterState = new HasQuarterState(this);    State * soldState = new SoldState(this);    State * soldOutState = new soldOutState(this);      this->count = numberGumballs;        if(numberGumballs > 0){            state = noQuarterState;        }    }       void insertQuarter(){        state->insertQuarter();    }    void setState(State * state){        this->state = state;    }    void releaseBall(){        cout << "A gumball comes rolling out the slot..."<<endl;        if(count>0){count--;}    }    // 重新装填    void refill(int count){        this->count=count;        state = noQuarterState;    }    // ...... getter() 如: getNoQuarterState()、getCount()};

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
将各种状态封装成独立的类,并将动作委托到当前状态的对象,因为行为会随着内部状态而改变。
使用组合通过简单引用不同的状态得到改变状态的假象。

在下面的两种情况下均可使用State模式:
1).一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2).代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

State对象可保证Context不会发生内部状态不一致的情况,因为从Context的角度看,状态转换是原子的—只需重新绑定一个变量(State对象变量).

状态转换:
这里写图片描述
这里写图片描述

这里写图片描述
将一群行为封装在状态对象中,context(对应于GumballMachine)的行为随时可以委托到那些状态对象中的一个。当前状态在状态集合中游走改变,来反应context内部状态,context的行为也会随着改变。context的客户并不会察觉。
将行为包装禁状态对象中,通过在context内简单的改变状态对象来改变context的行为。

Gumballmachine *g = new GumballMachine(5);g->insertQuarter();g->turnCrank();g->insertQuarter();g->insertQuarter();
0 0