Head First 设计模式:State Pattern状态模式(三)

    状态模式允许对象在内部状态改变时,改变它的行为。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状态了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yaked19

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值