zoukankan      html  css  js  c++  java
  • 设计模式01-状态模式

      设计模式概念接触到比较早,之前看看感觉各个模式讲的都差不多,可能感悟不深。最近研究一下,通过具体代码示例加深理解。

      今天学习的是状态模式。状态模式主要的精髓在于把各种状态抽象出来,每种状态的业务逻辑在各自的状态中去实现。把整体的业务逻辑抽象成一个具体调用各状态的类。整体的业务逻辑,即是在各状态类之间进行切换,调用。

      下面以自动售货机为例,说明状态模式。自动售货机为一个整体的业务逻辑对象,自动售货机可能有以下几种状态:

    1.未投币

    2.已投币

    3.准备出货

    4.售罄

    自动售货机对象可能有以下几个动作:

    1.投币

    2.退币

    3.按出货按钮

    4.出货

    类图如下:

    代码如下:

    自动售货机类:vendingMachin.h

     1 /************************************************************************/
     2 /* 
     3     自动售货机类.
     4 */
     5 /************************************************************************/
     6 
     7 #ifndef        __VENDINGMACHIN_H__
     8 #define        __VENDINGMACHIN_H__
     9 
    10 #include "hasMoneyState.h"
    11 #include "noMoney.h"
    12 #include "soldOut.h"
    13 #include "soldState.h"
    14 
    15 class VendingMachin
    16 {
    17 public:
    18     VendingMachin(int count);
    19     void    putMoney();
    20     void    backMoney();
    21     void    pressButton();
    22     void    outGoods();
    23 
    24     void    setState(MachineState* pstate);
    25     int        getCount();
    26     MachineState * getNoMoneyState();
    27     MachineState * getHasMoneyState();
    28     MachineState * getSoldState();
    29     MachineState * getSoldOutState();
    30 private:
    31     int                m_count;
    32     MachineState*    m_phasMoney;
    33     MachineState*    m_pnoMoney;
    34     MachineState*    m_psold;
    35     MachineState*    m_psoldOut;
    36     MachineState*    m_pcurrent;
    37 };
    38 
    39 #endif

    vendingMachin.cpp

    #include "vendingMachin.h"
    
    VendingMachin::VendingMachin(int count)
    {
    
        m_phasMoney = new HasMoneyState(this);
        m_psoldOut = new SoldOut(this);
        m_psold = new SoldState(this);
        m_pnoMoney = new NoMoney(this);
        
        
        if (count > 0)
        {
            m_count = count;
            setState(m_pnoMoney);
        }
    }
    
    int VendingMachin::getCount()
    {
        return m_count;
    }
    
    void VendingMachin::setState(MachineState* pstate)
    {
        m_pcurrent = pstate;
    }
    
    void VendingMachin::putMoney()
    {
        m_pcurrent->putMoney();
    }
    
    void VendingMachin::backMoney()
    {
        m_pcurrent->backMoney();
    }
    
    void VendingMachin::pressButton()
    {
        m_pcurrent->pressButton();
    
        // 如果当前状态为准备出货状态,则按下出货按钮,进行出货
        if (m_pcurrent->getState() == eSOLDING)
        {
            m_pcurrent->outGoods();
        }
    }
    
    void VendingMachin::outGoods()
    {
        //m_pcurrent->outGoods();
        if (m_count > 0)
        {
            m_count--;
            printf("售出一件商品
    ");
        }
    }
    
    MachineState* VendingMachin::getHasMoneyState()
    {
        return m_phasMoney;
    }
    
    MachineState* VendingMachin::getNoMoneyState()
    {
        return m_pnoMoney;
    }
    
    MachineState* VendingMachin::getSoldOutState()
    {
        return m_psoldOut;
    }
    
    MachineState* VendingMachin::getSoldState()
    {
        return m_psold;
    }

    状态基类:MachineState.h

    #ifndef __MACHINESTATE_H__
    #define __MACHINESTATE_H__
    
    #include <stdio.h>
    
    /************************************************************************/
    /*     
        模拟自动售货机状态基类
        对应四种状态 :已投币,未投币,出货,售罄
    */
    /************************************************************************/
    
    class VendingMachin;
    
    enum VendingState{eNOMONEY,eHASMONEY,eSOLDOUT,eSOLDING};
    
    class  MachineState
    {
    public:
    
        virtual ~MachineState(){}
    
        // 投钱
        virtual        void    putMoney() = 0;
    
        // 退钱
        virtual        void    backMoney() = 0;
    
        // 出货
        virtual        void    outGoods() = 0;  
    
        // 点击出货按钮
        virtual        void    pressButton() = 0;
    
        // 获取当前状态
        virtual        VendingState    getState() = 0;
    
    };
    
    #endif

    以下是四种状态类:

    未投币状态类:noMoney.h

    /************************************************************************/
    /* 
        未投币状态
    */
    /************************************************************************/
    
    #ifndef        __NOMONEY_H__
    #define        __NOMONEY_H__
    
    #include "machineState.h"
    
    class  NoMoney :public MachineState
    {
    public:
        NoMoney(VendingMachin* vm);
        virtual ~NoMoney();
    
        void    putMoney();
        void    backMoney();
        void    pressButton();
        void    outGoods();
        VendingState getState();
    
    protected:
        VendingMachin*        m_pVm;
    };
    
    #endif

    noMoney.cpp

    #include "noMoney.h"
    #include "vendingMachin.h"
    
    NoMoney::NoMoney(VendingMachin* vm)
    {
        m_pVm = vm;
    }
    
    NoMoney::~NoMoney()
    {
    
    }
    
    void NoMoney::putMoney()
    {
        printf("投币成功!
    ");
    
        // 状态设置为已投币
        m_pVm->setState(m_pVm->getHasMoneyState());
    }
    
    void NoMoney::backMoney()
    {
        printf("您未投币,想退钱?...
    ");
    }
    
    void NoMoney::pressButton()
    {
        printf("您未投币,想拿东西么?...
    ");
    }
    
    void NoMoney::outGoods()
    {
        printf("非法状态
    ");
    }
    
    VendingState NoMoney::getState()
    {
        return eNOMONEY;
    }

    已投币状态:hasMoneyState.h

    #include "machineState.h"
    
    #ifndef        __HASMONEYSTATE_H__
    #define        __HASMONEYSTATE_H__
    
    
    class HasMoneyState :public MachineState
    {
    public:
        HasMoneyState(VendingMachin*vm);
        virtual ~HasMoneyState();
    
        void    putMoney();
        void    backMoney();
        void    pressButton();
        void    outGoods();
        VendingState    getState();
    protected:
        VendingMachin*        m_pVm;
    
    };
    
    #endif
    
    
    
    
    #include "hasMoneyState.h"
    #include "vendingMachin.h"
    
    HasMoneyState::HasMoneyState(VendingMachin*vm)
    {
        m_pVm = vm;
    }
    
    HasMoneyState::~HasMoneyState()
    {
    
    }
    
    void HasMoneyState::putMoney()
    {
        printf("您已经投过币了,无需再投
    ");
    }
    
    void HasMoneyState::backMoney()
    {
        printf("退币成功
    ");
    
        // 状态改为未投币
        m_pVm->setState(m_pVm->getNoMoneyState());
    }
    
    void HasMoneyState::pressButton()
    {
        printf("您按下了取货按钮
    ");
    
        // 状态设置为待出货状态
        m_pVm->setState(m_pVm->getSoldState());
    }
    
    void HasMoneyState::outGoods()
    {
        printf("非法状态
    ");
    }
    
    VendingState HasMoneyState::getState()
    {
        return eHASMONEY;
    }

    准备出货状态:soldState

    /************************************************************************/
    /* 
        出货状态
    */
    /************************************************************************/
    
    #ifndef        __SOLDSTATE_H__
    #define        __SOLDSTATE_H__
    
    #include "machineState.h"
    
    class SoldState :public MachineState
    {
    public:
        SoldState(VendingMachin* vm);
        virtual ~SoldState();
    
        void    putMoney();
        void    backMoney();
        void    pressButton();
        void    outGoods();
        VendingState getState();
    protected:
        VendingMachin*        m_pVm;
    };
    
    #endif
    
    #include "soldState.h"
    #include "vendingMachin.h"
    
    SoldState::SoldState(VendingMachin* vm)
    {
        m_pVm = vm;
    }
    
    SoldState::~SoldState()
    {
    
    }
    
    void SoldState::putMoney()
    {
        printf("正在出货,请勿投币
    ");
    }
    
    void SoldState::backMoney()
    {
        printf("正在出货,没有可退的钱
    ");
    }
    
    void SoldState::pressButton()
    {
        printf("正在出货,请勿重复转动手柄
    ");
    }
    
    void SoldState::outGoods()
    {
        m_pVm->outGoods();
        if (m_pVm->getCount() >0 )
        {
            m_pVm->setState(m_pVm->getNoMoneyState());
        }
        else
        {
            printf("商品已经售罄
    ");
            m_pVm->setState(m_pVm->getSoldOutState());
        }
    
    }
    
    VendingState SoldState::getState()
    {
        return eSOLDING;
    }

    售罄状态:soldOut

    /************************************************************************/
    /* 
        售罄状态
    */
    /************************************************************************/
    
    #ifndef        __SOLDOUT_H__
    #define        __SOLDOUT_H__
    
    #include "machineState.h"
    
    class SoldOut :public MachineState
    {
    public:
        SoldOut(VendingMachin* vm);
        virtual ~SoldOut();
    
        void    putMoney();
        void    backMoney();
        void    pressButton();
        void    outGoods();
        VendingState getState();
    protected:
        VendingMachin*        m_pVm;
    };
    
    #endif
    
    #include "soldOut.h"
    #include "vendingMachin.h"
    
    SoldOut::SoldOut(VendingMachin* vm)
    {
        m_pVm = vm;
    }
    
    SoldOut::~SoldOut()
    {
    
    }
    
    void SoldOut::putMoney()
    {
        printf("投币失败,商品已售罄
    ");
    }
    
    void SoldOut::backMoney()
    {
        printf("您未投币,想退钱么?...
    ");
    }
    
    void SoldOut::pressButton()
    {
        printf("商品售罄,请勿按动按钮
    ");
    }
    
    void SoldOut::outGoods()
    {
        printf("非法状态
    ");
    }
    
    VendingState SoldOut::getState()
    {
        return eSOLDOUT;
    }

    测试代码:

    // State.cpp : 定义控制台应用程序的入口点。
    //
    #include "vendingMachin.h"
    
    int main(int argc, char* argv[])
    {
        VendingMachin *vm = new VendingMachin(10);
        
        vm->putMoney();
        vm->backMoney();
        vm->pressButton();
        vm->putMoney();
        vm->pressButton();
    
        vm->putMoney();
        vm->pressButton();
        vm->putMoney();
        vm->pressButton();
        vm->putMoney();
        vm->pressButton();
        vm->putMoney();
        vm->pressButton();
        vm->putMoney();
        vm->pressButton();
    
        vm->putMoney();
        vm->pressButton();
    
        vm->putMoney();
        vm->pressButton();
    
        vm->putMoney();
        vm->pressButton();
    
        vm->putMoney();
        vm->pressButton();
    
        vm->putMoney();
        vm->pressButton();
    
        return 0;
    }

     

  • 相关阅读:
    代码大全第二版-阅读笔记01
    进度日报表15
    进度日报表14
    第七周总结
    进度日报表13
    进度日报表12
    进度日报表11
    系统图表联动
    算符优先分析法
    《软件需求模式》阅读笔记(一)
  • 原文地址:https://www.cnblogs.com/spplus/p/4704973.html
Copyright © 2011-2022 走看看