/************************************************************
CStatePattern.h
************************************************************/
#pragma once
#include <iostream>
using namespace std;
class CState;
class CSoldState;
class CSoldOutState;
class CNoQuarterState;
class CHasQuarterState;
//游戏机
class CGumballMachine
{
friend class CState;
friend class CSoldState;
friend class CSoldOutState;
friend class CNoQuarterState;
friend class CHasQuarterState;
private:
CState* m_sold;
CState* m_soldout;
CState* m_noQuarter;
CState* m_hasQuarter;
CState* m_currentState;
int m_ballCount;
public:
CGumballMachine();
~CGumballMachine();
private:
//get && set方法
void setState(CState* inState){
m_currentState = inState;
}
CState* getSoldState(){
return m_sold;
}
CState* getSoldoutState(){
return m_soldout;
}
CState* getNoQuarterState(){
return m_noQuarter;
}
CState* getHasQuarterState(){
return m_hasQuarter;
}
CState* getCurrentState(){
return m_currentState;
}
void releaseBall(){
cout<<"您得到了一颗糖果"<<endl;
m_ballCount--;
}
bool haveBall(){
return m_ballCount <= 0 ? true : false;
}
public:
///////操作
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
};
////////////////////////////////////
//状态的基类
class CState
{
public:
//以下是四个有可能会导致状态转换的动作.
virtual void insertQuarter() = 0;
virtual void ejectQuarter() = 0;
virtual void turnCrank() = 0;
virtual void dispense() = 0;
virtual ~CState() {}
};
////////////////////////////////////
//这个例子中,一开始会有四个状态,当然后来又加入了一个状态.
class CSoldState : public CState
{
private:
CGumballMachine* m_machine;
public:
CSoldState(CGumballMachine *inM) : m_machine(inM){}
void insertQuarter(){
cout<<"已经有硬币了,请按dispense按钮来取得糖果"<<endl;
}
void ejectQuarter(){
cout<<"糖果已经在准备中了,不可退钱"<<endl;
}
void turnCrank(){
cout<<"你转两次不会给你两颗糖.嘿嘿"<<endl;
}
void dispense(){
m_machine->releaseBall();
if(m_machine->haveBall())
m_machine->setState(m_machine->getNoQuarterState());
else
m_machine->setState(m_machine->getSoldoutState());
}
};
class CSoldOutState : public CState
{
private:
CGumballMachine* m_machine;
public:
CSoldOutState(CGumballMachine *inM) : m_machine(inM){}
void insertQuarter(){
cout<<"糖果机里已经没有糖果了"<<endl;
}
void ejectQuarter(){
cout<<"没有硬币在糖果机里"<<endl;
}
void turnCrank(){
cout<<"没有硬币在糖果机里"<<endl;
}
void dispense(){
cout<<"没硬币,糖果机里也没糖果了"<<endl;
}
};
class CNoQuarterState : public CState
{
private:
CGumballMachine* m_machine;
public:
CNoQuarterState(CGumballMachine *inM) : m_machine(inM){}
void insertQuarter(){
cout<<"投入了硬币"<<endl;
m_machine->setState(m_machine->getHasQuarterState());
}
void ejectQuarter(){
cout<<"没有投入任何硬币"<<endl;
}
void turnCrank(){
cout<<"你转了,但是没有硬币"<<endl;
}
void dispense(){
cout<<"你要先付钱"<<endl;
}
};
class CHasQuarterState : public CState
{
private:
CGumballMachine* m_machine;
public:
CHasQuarterState(CGumballMachine *inM) : m_machine(inM){}
void insertQuarter(){
cout<<"糖果机中已经有硬币了"<<endl;
}
void ejectQuarter(){
cout<<"硬币已经返回"<<endl;
m_machine->setState(m_machine->getNoQuarterState());
}
void turnCrank(){
cout<<"请稍等,一会儿按dispense按钮,你就可以得到一颗糖"<<endl;
m_machine->setState(m_machine->getSoldState());
}
void dispense(){
cout<<"没有糖果分发,请先turnCrank"<<endl;
}
};
/****************************************************************
CStatePattern.cpp
****************************************************************/
#include "CStatePattern.h"
CGumballMachine::CGumballMachine()
{
m_sold = new CSoldState(this);
m_soldout = new CSoldOutState(this);
m_noQuarter = new CNoQuarterState(this);
m_hasQuarter= new CHasQuarterState(this);
//设定初始状态
m_currentState = m_noQuarter;
//初始有100颗糖
m_ballCount = 100;
}
CGumballMachine::~CGumballMachine(){
if(m_sold)
delete m_sold;
if(m_soldout)
delete m_soldout;
if(m_noQuarter)
delete m_noQuarter;
if(m_hasQuarter)
delete m_hasQuarter;
}
void CGumballMachine::insertQuarter()
{
m_currentState->insertQuarter();
}
void CGumballMachine::ejectQuarter()
{
m_currentState->ejectQuarter();
}
void CGumballMachine::turnCrank()
{
m_currentState->turnCrank();
}
void CGumballMachine::dispense()
{
m_currentState->dispense();
}
/***********************************************************
testStatePattern.cpp
***********************************************************/
/*
设计模式: 状态模式
允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类.(has-a)
这个模式它将状态封装成为独立的类, 并将动作委托到代表当前状态的对象. 当动作发生时, 状态有可能发生改变,
当状态改变时当前状态在状态对象集合中游走改变,以后反映出context新的内部状态.(就是把一个成员状态赋给当前状态).
但是用这个context的客户就完全不会知道在context内部到底做了什么.
在这种模式的支撑下,想要为某个状态机新增一种状态,我们只需要新加一个状态类即可.
这样就可以大幅提高这个状态机的可修改程度了.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
这个程序的功能是书上糖果机的一个例子.
状态图详见P386
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/
#include <iostream>
#include "CStatePattern.h"
using namespace std;
int main()
{
CGumballMachine* gm = new CGumballMachine();
gm->turnCrank();
gm->dispense();
gm->insertQuarter();
gm->dispense();
gm->turnCrank();
gm->dispense();
delete gm;
return 0;
}