zoukankan      html  css  js  c++  java
  • 设计模式之实现状态模式

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

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

  • 相关阅读:
    easyui 单元格超出鼠标放上弹出全部
    EasyUI datagrid单元格文本超出显示省略号,鼠标移动到单元格显示文本
    easyui 回车搜索
    js控制easyui文本框例子及控制html例子
    Android错误---NoClassDefFoundError: org.ksoap2.transport.HttpTransportSE
    [Android错误]The literal 100000000000000 of type int is out of range
    Eclipse错误:Conversion to Dalvik format failed with error 1
    Android微信分享音乐加网络图片失败分析
    android.view.WindowManager$BadTokenException异常
    Android错误--Attempted to add application window with unknown token
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/2756555.html
Copyright © 2011-2022 走看看