- 定义一个State接口。在接口内,糖果机每个动作对应一个方法。
- 为机器中的每个状态实现状态类。这些类负责在对应的状态下进行机器的行为。
- 将动作委托到状态类。
状态 | 描述 |
---|---|
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();