设计模式之实现状态模式

/************************************************************

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;
}

原文地址:https://www.cnblogs.com/skyofbitbit/p/2756555.html