状态模式c++实现

Posted 今天也要努力搬砖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状态模式c++实现相关的知识,希望对你有一定的参考价值。

参考书籍《Head First设计模式》

需求场景

           糖果机有4种状态:有25分钱,没有25分钱,售出糖果,糖果售罄。各个状态之间的转换如下图

 

         如果不使用状态模式,直接写代码的话,就是一堆if-else或者switch控制语句,其实单独对这个例子来说,这没有任何问题。但是如果考虑到后面有新的状态加入就要改这一块if-else或者switch,这违背了开放-关闭原则:对修改关闭,对扩展开放。如果使用状态模式,将会看见没有一个if-else(实际上是把条件判断放在了设计代码阶段,每个状态对应一个ConcerateState,该状态支持哪些状态流转就实现对应的接口,这一点在下面代码种会看到,比如从状态图中可以看出没有25分钱的状态只支持投入硬币的动作,体现在代码中即NoQuarterState类只重新实现了父类的insertQuarter方法)。

模式定义

        状态模式运行对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

        类图如下

        

代码实现

         首先,定义一个State虚基类。在这个类内,糖果机的每个动作都有一个对应的方法,在该基类中这些方法都是空实现(只打印log)。State持有一个GumballMachine的实例,目的是取得目标状态实例(代码中getXXState()))

    

class State 
public:
	State(GumballMachine* gumballMachine);
	//投入硬币
	virtual void insertQuarter();
	//退出硬币
	virtual void ejectQuarter();

	//转动旋柄
	virtual void turnCrank();

	//发放糖果
	virtual void dispense();
protected:
	GumballMachine* gumballMachine_;

;
State::State(GumballMachine* gumballMachine) :gumballMachine_(gumballMachine)



void State::insertQuarter()

	std::cout << "Current state dose not support insert Quarter,do nothing." << std::endl;


 void State::ejectQuarter()

	std::cout << "Current state dose not support eject Quarter,do nothing." << std::endl;


void State::turnCrank()

	std::cout << "Current state dose not support turn Crank,do nothing." << std::endl;


 void State::dispense()

	std::cout << "Current state dose not support dispense,do nothing." << std::endl;

       

      然后为机器中的每个状态实现状态类。每个状态类实现自己支持的虚基类中的某些接口,来实现对应状态下机器的行为。

    

class NoQuarterState :public State 
public:
	NoQuarterState(GumballMachine* gumballMachine);
	//投入硬币
	virtual void insertQuarter()override;

;

class HasQuarterState :public State 
public:
	HasQuarterState(GumballMachine* gumballMachine);
	//退出硬币
	virtual void ejectQuarter() override;

	//转动旋柄
	virtual void turnCrank() override;
;

class SoldState :public State 
public:
	SoldState(GumballMachine* gumballMachine);
	//发放糖果
	virtual void dispense() override;
;

class SoldOutState :public State 
public:
	SoldOutState(GumballMachine* gumballMachine);
;

NoQuarterState::NoQuarterState(GumballMachine* gumballMachine):State(gumballMachine)

	


void NoQuarterState::insertQuarter()

	std::cout << "You insert a quarter." << std::endl;
	gumballMachine_->setState(gumballMachine_->getHasQuarterState());



HasQuarterState::HasQuarterState(GumballMachine* gumballMachine) :State(gumballMachine)




void HasQuarterState::ejectQuarter()

	std::cout << "Quarter returned." << std::endl;
	gumballMachine_->setState(gumballMachine_->getNoQuarterState());


void HasQuarterState::turnCrank()

	std::cout << "You turned...." << std::endl;
	gumballMachine_->setState(gumballMachine_->getSoldState());


SoldState::SoldState(GumballMachine* gumballMachine) :State(gumballMachine)




void SoldState::dispense()

	gumballMachine_->releaseBall();
	if (gumballMachine_->getCounter() > 0)
	
		gumballMachine_->setState(gumballMachine_->getNoQuarterState());
	
	else
	
		std::cout << "Oops,out of gumballs." << std::endl;
		gumballMachine_->setState(gumballMachine_->getSoldOutState());
	


SoldOutState::SoldOutState(GumballMachine* gumballMachine) :State(gumballMachine)


     最后,在糖果机类GumBallMachine中,将动作委托给状态类。

class GumballMachine 
public:
	GumballMachine(int numberGumballs);
	~GumballMachine();
	void insertQuarter();
	void ejectQuarter();
	void turnCrank();
	void setState(State* state);
	void releaseBall();
	State* getSoldOutState();
	State* getNoQuarterState();
	State* getHasQuarterState();
	State* getSoldState();
	int getCounter();
private:
	State* soldOutState_;
	State* noQuarterState_;
	State* hasQuarterState_;
	State* soldState_;

	State* currentState_ ;
	int count_;
;
GumballMachine::GumballMachine(int numberGumballs)

	soldOutState_ = new  SoldOutState(this);
	noQuarterState_ = new  NoQuarterState(this);
	hasQuarterState_ = new  HasQuarterState(this);
	soldState_ = new  SoldState(this);

	count_ = numberGumballs;
	if(count_>0)
		currentState_ = noQuarterState_;
	else
		currentState_ = soldOutState_;


GumballMachine::~GumballMachine()

	delete soldOutState_;
	soldOutState_ = nullptr;
	delete noQuarterState_;
	noQuarterState_ = nullptr;
	delete hasQuarterState_;
	hasQuarterState_ = nullptr;
	delete soldState_;
	soldState_ = nullptr;


void GumballMachine::insertQuarter()

	currentState_->insertQuarter();

void GumballMachine::ejectQuarter()

	currentState_->ejectQuarter();

void GumballMachine::turnCrank()

	currentState_->turnCrank();
	currentState_->dispense();

void GumballMachine::setState(State* state)

	currentState_ = state;

void GumballMachine::releaseBall()

	std::cout << "A gumball comes rolling out the solt...."<< std::endl;
	if (count_ > 0)
		count_--;

最后测试场景如下,糖果机里面放3颗糖,连续投硬币,转动曲柄,观察糖果机状态。

测试代码如下

int main()

	GumballMachine gumballMachine(3);
	gumballMachine.insertQuarter();
	gumballMachine.turnCrank();
	gumballMachine.insertQuarter();
	gumballMachine.turnCrank();
	gumballMachine.insertQuarter();
	gumballMachine.turnCrank();
	gumballMachine.insertQuarter();
	gumballMachine.turnCrank();
	system("pause");

   

 运行测试效果如下

   

 

 

        


       

以上是关于状态模式c++实现的主要内容,如果未能解决你的问题,请参考以下文章

状态模式c++实现

状态模式c++实现

《Head First 设计模式》之状态模式——糖果机

华为机试真题 C++ 实现分糖果

[编程题] 糖果谜题 C++实现输入未知个整数

两种语言实现设计模式(C++和Java)(十六:状态模式)