状态模式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++实现的主要内容,如果未能解决你的问题,请参考以下文章