状态模式允许对象在内部状态改变时,改变它的行为。P410类图
#include<iostream>
using std::cout;
using std::endl;
//***********************************************
// State Interface.
//***********************************************
class State
{
public :
virtual void insertMoney() = 0;
virtual void ejectMoney() = 0;
virtual void turnCrank() = 0;
virtual void dispense() = 0;
};
//***********************************************
// NoMoneyState implements state Interface.
//***********************************************
class NoMoneyState : public State
{
CandyMachine* candymachine;
public:
NoMoneyState(){
};
NoMoneyState(CandyMachine* candymachine)
{
this->candymachine = candymachine;
};
public:
void insertMoney()
{
cout<< "You insert money."<<endl;
}
virtual void dispense()
{
cout<< "You need pay first."<<endl;
}
virtual void turnCrank()
{
cout<< "You turned Crank but you haven't insert money."<<endl;
}
virtual void ejectMoney()
{
cout<< "You haven't insert money."<<endl;
}
};
//***********************************************
// HasMoneyState implements state Interface.
//***********************************************
class HasMoneyState : public State
{
CandyMachine* candymachine;
public:
HasMoneyState(){
};
HasMoneyState(CandyMachine* candymachine)
{
this->candymachine = candymachine;
};
public:
virtual void insertMoney()
{
printf("HasMoneyState_insertMoney, Already have money.\n");
}
virtual void dispense()
{
printf("HasMoneyState_dispense, No candy dispense.\n");
}
virtual void turnCrank()
{
printf("HasMoneyState_turnCrank, You turned...\n");
candymachine->setState(candymachine->getSoldState());
}
virtual void ejectMoney()
{
printf("HasMoneyState_ejectMoney,Money returning...\n");
candymachine->setState(candymachine->getSoldOutState());
}
};
//***********************************************
// SoldState implements state Interface.
//***********************************************
class SoldState : public State
{
CandyMachine* candymachine;
public:
SoldState()
{
};
SoldState(CandyMachine* candymachine)
{
this->candymachine = candymachine;
};
public:
virtual void insertMoney()
{
printf("SoldState_insertMoney, Please Wait, already giving you a candy.\n");
}
virtual void turnCrank()
{
printf("SoldState_turnCrank, Turning twice doesn't give you more.\n");
}
virtual void ejectMoney()
{
printf("SoldState_ejectMoney, Sorry,you already turned the crank.\n");
}
virtual void dispense()
{
candymachine->releasecandy();
if (candymachine->getCount() > 0)
{
candymachine->setState(candymachine->getNoMoneyState());
}
else
{
printf("SoldState_dispense, Out of candy.\n");
candymachine->setState(candymachine->getSoldOutState());
}
}
};
//***********************************************
// SoldOutState implements state Interface.
//***********************************************
//class CandyMachine; // forward reference
class SoldOutState : public State
{
CandyMachine* candymachine;
public:
SoldOutState()
{
};
SoldOutState(CandyMachine* candymachine)
{
this->candymachine = candymachine;
};
public:
virtual void insertMoney()
{
printf("SoldOutState_insertMoney, you can't insert, Sold Out.\n");
}
virtual void dispense()
{
printf("SoldOutState_dispense, No candy to sell.\n");
}
virtual void turnCrank()
{
printf("SoldOutState_ejectMoney, Out of candy..\n");
}
virtual void ejectMoney()
{
/*throw std::logic_error("The method or operation is not implemented.");*/
printf("SoldOutState_ejectMoney, you insert no money.\n");
}
};
class CandyMachine
{
State* noMoneyState;
State* hasMoneyState;
State* soldState;
State* soldOutState;
State* state ;
int count ;
public:
CandyMachine(int numbercandy)
{
noMoneyState = new NoMoneyState(this);
hasMoneyState = new HasMoneyState(this);
soldState = new SoldState(this);
soldOutState = new SoldOutState(this);
this->state = soldOutState; // Is it right if state = soldOutState?
this->count = 0;
this->count = numbercandy;
if (numbercandy > 0)
{
this->state = noMoneyState;
}
}
void insertMoney()
{
state->insertMoney();
}
void ejectMoney()
{
state->ejectMoney();
}
void turnCrank()
{
state->turnCrank();
state->dispense();
}
void releasecandy()
{
cout<< "Candy coming out!!"<<endl;
if (cout != 0 )
{
count = count -1;
}
}
void setState(State* state)
{
this->state = state;
}
State* getNoMoneyState()
{
return this->noMoneyState;
}
State* getHasMoneyState()
{
return this->hasMoneyState;
}
State* getSoldState()
{
return this->soldState;
}
State* getSoldOutState()
{
return this->soldOutState;
}
int getCount()
{
return this->count;
}
};
因为编译原因,我把它分开了,写成了多个类
1. 前向声明(注意,不能实例化类的对象,但可以定义类类型指针State*)
2. main函数
3. 类图
总结:
1. 状态模式有点像策略模式,拥有一个接口(在这里是State接口),委托给相应子类处理。比如candymachine->insertMoney,委托后就是State.insertMoney, 这里的State就是根据不同状态去调用自己的方法,如果是NoMoneyState就调用noMoneyState.insertMoney,(因为在CandyMachine内部维护了四个状态和当前状态,保存在state变量中)。
2. 不同之处在于,在每个接口子类中,它们各自又维护了一个candymachine对象,它的作用就是用来切换状态的。例如,
void HasMoneyState::turnCrank()
{
printf("HasMoneyState_turnCrank, You turned...\n");
candymachine->setState(candymachine->getSoldState());
}
在HasMoneyState,转动手柄,就切换到了SoldState状态了。