`

[行为模式] state模式

阅读更多
问题
每个人、事物在不同的状态下会有不同表现(动作),而一个状态又会在不同的表现下转移到下一个不同的状态(State)。最简单的一个生活中的例子就是:地铁入口处,如果你放入正确的地铁票,门就会打开让你通过。在出口处也是验票,如果正确你就可以ok,否则就不让你通过(如果你动作野蛮,或许会有报警(Alarm),:))。
有限状态自动机(FSM)也是一个典型的状态不同,对输入有不同的响应(状态转移)。通常我们在实现这类系统会使用到很多的Switch/Case语句,Case某种状态,发生什么动作,Case另外一种状态,则发生另外一种状态。但是这种实现方式至少有以下两个问题:
1)当状态数目不是很多的时候,Switch/Case可能可以搞定。但是当状态数目很多的时候(实际系统中也正是如此),维护一大组的Switch/Case语句将是一件异常困难并且容易出错的事情。
2)状态逻辑和动作实现没有分离。在很多的系统实现中,动作的实现代码直接写在状态的逻辑当中。这带来的后果就是系统的扩展性和维护得不到保证。

模式选择
State模式就是被用来解决上面列出的两个问题的,在State模式中我们将状态逻辑和动作实现进行分离。当一个操作中要维护大量的case分支语句,并且这些分支依赖于对象的状态。State模式将每一个分支都封装到独立的类中。

实现
请看附件 state.zip
PS:也可以参考blaze中的代码 loginstatemachine.cpp

纯虚函数的测试
在写测试代码的时候,偶然发现在父类确定纯虚函数的时候居然也可以有一个实现体,很奇怪!!!于是也写了代码测试了一下,总结出规律如下(不一定完全正确,完全是个人理解)
1)父类在定义纯虚函数的时候,可以有实现体,但是没有任何意义,因为父类不能实例化,这段代码永远不会被调用到;
2)子类在继承父类的时候,可以不实现纯虚函数体;但是前提是,这个子类不会被实例化
3)子类在继承父类的时候,如果需要实例化,就必须实现纯虚函数,不然虚表中对应函数的地址就无法确定,编译出错。
4)测试代码请见PureVirtualTest.zip


下面的部分请看以下链接http://blog.csdn.net/hguisu/article/details/7557252
#ifndef NORMAL_H
#define NORMAL_H

typedef enum  Em_Algorithm_TYPE
{
    AlgorithmType_SHA1    = 1,
    AlgorithmType_SHA256  = 2
}ALGORITHM_TYPE, *PALGORITHM_TYPE;

typedef enum Em_Lift_Type
{
    //电梯的四个状态  
    OPENING_STATE = 1, //门敞状态  
    CLOSING_STATE = 2,  //门闭状态  
    RUNNING_STATE = 3,  //运行状态  
    STOPPING_STATE = 4 //停止状态;  
}LIFT_TYPE;

class ILift
{
public:
    ILift();
    virtual ~ILift();

    //设置电梯的状态  
    virtual void setState(LIFT_TYPE emStateType) = 0;

    //首先电梯门开启动作  
    virtual void open() = 0;

    //电梯门有开启,那当然也就有关闭了  
    virtual void close() = 0;

    //电梯要能上能下,跑起来  
    virtual void run() = 0;

    //电梯还要能停下来,停不下来那就扯淡了
    virtual void stop() = 0;
};


class Lift : public  ILift
{
public:
    Lift();
    virtual ~Lift();

    virtual void setState(LIFT_TYPE emStateType);

    //电梯门关闭
    virtual void close();

    //电梯门开启
    virtual void open();

    ///电梯开始跑起来
    virtual void run();

    //电梯停止
    virtual void stop();

private:
    LIFT_TYPE m_LiftYype;
};

void Lift_Run();

#endif //NORMAL_H




#include "Normal.h"
#include <iostream>
using namespace std;

//////////////////////////////////////////////////////////////////////////
ILift::ILift()
{

}

ILift::~ILift()
{

}

//////////////////////////////////////////////////////////////////////////
Lift::Lift()
{

}

Lift::~Lift()
{

}

void Lift::setState(LIFT_TYPE emStateType)
{
    this->m_LiftYype = emStateType;
}  

//电梯门关闭  
void Lift::close()
{
    //电梯在什么状态下才能关闭  
    switch(this->m_LiftYype)
    {
    case OPENING_STATE:  //如果是则可以关门,同时修改电梯状态
        {
            this->setState(CLOSING_STATE);
            cout << "OPENING_STATE ==> CLOSING_STATE" << endl;
            break;
        }
    case CLOSING_STATE:  //如果电梯就是关门状态,则什么都不做
        {
            //do nothing;
            cout << "CLOSING_STATE" << endl;
            break;
        }
    case RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做  
        {
            //do nothing;
            cout << "RUNNING_STATE" << endl;
            break;
        }
    case STOPPING_STATE:  //如果是停止状态,本也是关闭的,什么也不做
        {
            //do nothing;
            cout << "RUNNING_STATE" << endl;
            break;
        }
    }
}

//电梯门开启  
void Lift::open() 
{
    //电梯在什么状态才能开启
    switch(this->m_LiftYype)
    {
    case OPENING_STATE: //如果已经在门敞状态,则什么都不做
        {
            //do nothing;
            cout << "OPENING_STATE" << endl;
            break;
        }
    case CLOSING_STATE: //如是电梯时关闭状态,则可以开启
        {
            this->setState(OPENING_STATE);
            cout << "CLOSING_STATE ==> OPENING_STATE" << endl;
            break;
        }
    case RUNNING_STATE: //正在运行状态,则不能开门,什么都不做
        {
            //do nothing;
            cout << "RUNNING_STATE" << endl;
            break;
        }
    case STOPPING_STATE: //停止状态,淡然要开门了
        {
            this->setState(OPENING_STATE);
            cout << "STOPPING_STATE ==> OPENING_STATE" << endl;
            break;
        }
    }
}  
///电梯开始跑起来  
void Lift::run()
{  
    switch(this->m_LiftYype)
    {
    case OPENING_STATE: //如果已经在门敞状态,则不你能运行,什么都不做
        {
            //do nothing;
            cout << "OPENING_STATE" << endl;
            break;
        }
    case CLOSING_STATE: //如是电梯时关闭状态,则可以运行
        {
            this->setState(RUNNING_STATE);
            cout << "CLOSING_STATE ==> RUNNING_STATE" << endl;
            break;
        }
    case RUNNING_STATE: //正在运行状态,则什么都不做
        {
            //do nothing;
            cout << "RUNNING_STATE" << endl;
            break;
        }
    case STOPPING_STATE: //停止状态,可以运行
        {
            this->setState(RUNNING_STATE);
            cout << "STOPPING_STATE ==> RUNNING_STATE" << endl;
            break;
        }
    }
}

//电梯停止
void Lift::stop()
{
    switch(this->m_LiftYype)
    {
        case OPENING_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做
            {
                //do nothing;  
                cout << "OPENING_STATE" << endl;
                break;
            }
        case CLOSING_STATE: //如是电梯时关闭状态,则当然可以停止了
            {
                this->setState(CLOSING_STATE);
                cout << "CLOSING_STATE ==> CLOSING_STATE" << endl;
            break;
            }
        case RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了
            {
                this->setState(CLOSING_STATE);
                cout << "RUNNING_STATE ==> CLOSING_STATE" << endl;
                break;
            }
        case STOPPING_STATE: //停止状态,什么都不做
            {
                //do nothing;
                cout << "STOPPING_STATE" << endl;
                break;
            }
    }
}

//////////////////////////////////////////////////////////////////////////
void Lift_Run()
{
    Lift* pList = new Lift();

    //电梯的初始条件应该是停止状态
    pList->setState(STOPPING_STATE);

    //首先是电梯门开启,人进去
    pList->open();

    //然后电梯门关闭
    pList->close();

    //再然后,电梯跑起来,向上或者向下
    pList->run();

    //最后到达目的地,电梯挺下来
    pList->stop();
}




#ifndef STATE_H
#define STATE_H

#include <Windows.h>

class Context;

class LiftState
{
public:
    LiftState();
    virtual ~LiftState();

    void setContext(Context* pContext);

    //首先电梯门开启动作
    virtual void open() = 0;

    //电梯门有开启,那当然也就有关闭了
    virtual void close() = 0;

    //电梯要能上能下,跑起来
    virtual void run() = 0;

    //电梯还要能停下来,停不下来那就扯淡了
    virtual void stop() = 0;

protected:
    //定义一个环境角色,也就是封装状态的变换引起的功能变化  
    Context* m_pContext;
};

class OpenningState;
class CloseingState;
class RunningState;
class StoppingState;

class Context
{

public:
    Context();
    virtual ~Context();

    LiftState* getLiftState();

    void setLiftState(LiftState* pLiftState);


    void open();

    void close();

    void run();

    void stop();

private:
    //定一个当前电梯状态  
    LiftState* m_pLiftState;

public:
    //定义出所有的电梯状态  
    OpenningState* m_pOpenningState;
    CloseingState* m_pCloseingState;
    RunningState*  m_pRunningState;
    StoppingState* m_pStoppingState;
};

class OpenningState : public LiftState
{
public:
    OpenningState();
    virtual ~OpenningState();

    virtual void close();

    virtual void  open();
 
    virtual void run();

    virtual void stop();
};

class CloseingState : public LiftState
{
public:
    CloseingState();
    virtual ~CloseingState();

    virtual void close();

    virtual void  open();

    virtual void run();

    virtual void stop();
};

class RunningState : public LiftState
{
public:
    RunningState();
    virtual ~RunningState();

    virtual void close();

    virtual void  open();

    virtual void run();

    virtual void stop();
};

class StoppingState : public LiftState
{
public:
    StoppingState();
    virtual ~StoppingState();

    virtual void close();

    virtual void  open();

    virtual void run();

    virtual void stop();
};

void State_Run();

#endif STATE_H



#include "State.h"

//////////////////////////////////////////////////////////////////////////
LiftState::LiftState()
{
    m_pContext = NULL;
}

LiftState::~LiftState()
{

}

void LiftState::setContext(Context* pContext)
{  
    this->m_pContext =pContext;
}

//////////////////////////////////////////////////////////////////////////
Context::Context()
{
    m_pLiftState = NULL;
    m_pOpenningState = new OpenningState();
    m_pCloseingState = new CloseingState();
    m_pRunningState = new RunningState();
    m_pStoppingState = new StoppingState();
}
Context::~Context()
{

}

LiftState* Context::getLiftState()
{
    return this->m_pLiftState;
}  

void Context::setLiftState(LiftState* pLiftState)
{
    this->m_pLiftState = pLiftState;

    //把当前的环境通知到各个实现类中
    this->m_pLiftState->setContext(this);
}  


void Context::open()
{
    this->m_pLiftState->open();
}  

void Context::close()
{
    this->m_pLiftState->close();
}

void Context::run()
{
    this->m_pLiftState->run();
}

void Context::stop()
{
    this->m_pLiftState->stop();
}

//////////////////////////////////////////////////////////////////////////
OpenningState::OpenningState()
{

}

OpenningState::~OpenningState()
{

}

void OpenningState::close()
{
    //状态修改  
    this->m_pContext->setLiftState(this->m_pContext->m_pColseingState);
    //动作委托为CloseState来执行  
    this->m_pContext->getLiftState()->close();
}  

//打开电梯门  
void OpenningState::open()
{
    //echo 'lift open...', '<br/>';  
}
//门开着电梯就想跑,这电梯,吓死你!  
void OpenningState::run()
{
    //do nothing;  
}

//开门还不停止?
void OpenningState::stop()
{
    //do nothing;  
}

//////////////////////////////////////////////////////////////////////////
CloseingState::CloseingState()
{

}

CloseingState::~CloseingState()
{

}

//电梯门关闭,这是关闭状态要实现的动作  
void CloseingState::close()
{
    //echo 'lift close...', '<br/>';
}

//电梯门关了再打开,逗你玩呢,那这个允许呀
void CloseingState::open()
{
    this->m_pContext->setLiftState(this->m_pContext->m_pOpenningState);  //置为门敞状态
    this->m_pContext->getLiftState()->open();
}

//电梯门关了就跑,这是再正常不过了
void CloseingState::run()
{
    this->m_pContext->setLiftState(this->m_pContext->m_pRunningState); //设置为运行状态
    this->m_pContext->getLiftState()->run();  
}

//电梯门关着,我就不按楼层
void CloseingState::stop()
{
    this->m_pContext->setLiftState(this->m_pContext->m_pStoppingState);  //设置为停止状态
    this->m_pContext->getLiftState()->stop();  
}  
//////////////////////////////////////////////////////////////////////////
RunningState::RunningState()
{

}

RunningState::~RunningState()
{

}

//电梯门关闭?这是肯定了  
void RunningState::close() {  
    //do nothing  
}  

//运行的时候开电梯门?你疯了!电梯不会给你开的  
void RunningState::open()
{
    //do nothing  
}  

//这是在运行状态下要实现的方法  
void RunningState::run()
{
    //echo 'lift run...', '<br/>';
}

//这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了  
void RunningState::stop()
{
    this->m_pContext->setLiftState(this->m_pContext->m_pStoppingState); //环境设置为停止状态;
    this->m_pContext->getLiftState()->stop();  
}
//////////////////////////////////////////////////////////////////////////
StoppingState::StoppingState()
{

}

StoppingState::~StoppingState()
{

}
//停止状态关门?电梯门本来就是关着的!  
void StoppingState::close() {  
    //do nothing;  
}  

//停止状态,开门,那是要的!
void StoppingState::open()
{
    this->m_pContext->setLiftState(this->m_pContext->m_pOpenningState);
    this->m_pContext->getLiftState()->open();  
}
//停止状态再跑起来,正常的很  
void StoppingState::run()
{
    this->m_pContext->setLiftState(this->m_pContext->m_pRunningState);
    this->m_pContext->getLiftState()->run();
}

//停止状态是怎么发生的呢?当然是停止方法执行了
void StoppingState::stop()
{
    //echo 'lift stop...', '<br/>';  
}  



//////////////////////////////////////////////////////////////////////////
void State_Run()
{
    Context* pContext = new Context();
    pContext->setLiftState(new CloseingState());

    pContext->open();
    pContext->close();
    pContext->run();
    pContext->stop();
}




#include "Normal.h"
#include "State.h"
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{

    //////////////////////////////////////////////////////////////////////////
    Lift_Run();
    State_Run();

    return 0;
}
分享到:
评论

相关推荐

    设计模式State模式源码

    State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 不只是根据状态,也有根据属性.如果...

    C#面向对象设计模式纵横谈(22):(行为型模式) State 状态模式

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。在C#编程中,这种模式被广泛应用于处理具有多种状态的对象,使得对象的状态转换更加清晰和易于管理。 状态模式的...

    JAVA设计模式之行为模式

    这是JAVA设计模式中属于行为模式的部分,包括Template(模板模式)、Chain of Responsibility(责任链模式)、Memento(纪念品模式)、Mediator(中介模式)、Strategy(策略模式)、State 、Observer(观察者模式)、Visitor...

    设计模式_行为模式

    在这个“设计模式_行为模式”主题中,我们将深入探讨几种关键的行为模式。 1. 责任链模式(Chain of Responsibility):此模式允许创建一个处理请求的对象链,每个对象都可以处理请求或将其传递给链中的下一个对象...

    状态模式 State Pattern

    ### 状态模式(State Pattern) #### 概念与定义 状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为,使对象看起来像是修改了它的类。该模式通过引入一个代表各种状态的类以及一个行为随着这些...

    Android的状态机模式StateMachine与State

    在博文《Android的状态机模式StateMachine与State》中,作者可能会详细介绍如何创建和使用这两种组件。通常,状态机的实现会涉及到以下步骤: 1. **定义状态接口或抽象类**:创建一个State接口或抽象类,其中包含...

    状态模式(State Pattern)是一种行为设计模式

    状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式将一个对象的行为分解为各个独立的状态,并且每个状态都封装在自己的类中,使得对象在...

    轻松掌握state设计模式

    State模式是一种行为型设计模式,用于在不改变对象自身的情况下改变其行为。它的核心思想是:通过引入一系列的具体状态类来表示对象的不同状态,并将这些状态封装为独立的类,从而使对象能够在这些状态之间自由切换...

    设计模式之状态模式State

    状态模式通常包含三个主要角色:Context(上下文)、State(抽象状态)和ConcreteState(具体状态)。 上下文是拥有状态的对象,它定义了与该状态相关的接口,并负责在适当的时候将请求委托给相应的状态对象处理。...

    设计模式之状态模式(State Pattern)

    状态模式是一种行为设计模式,它使你能在运行时改变对象的行为。在状态模式中,一个对象的状态变化会导致其行为的变化,这种变化不是通过改变对象的类来实现的,而是通过改变对象的状态。这个模式的核心是封装可能...

    C#面向对象设计模式谈之行为模式

    本篇将重点讨论C#中的行为模式,特别是备忘录模式。 备忘录模式是一种行为设计模式,它在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将对象恢复到原先保存的状态。...

    设计模式原理与应用之行为模式.pptx

    State模式是一种行为模式,旨在解决允许一个对象在其内部状态改变时改变它的行为的问题。该模式可以允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。 Strategy模式 Strategy模式是一种...

    设计模式C++学习之状态模式(State)

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且使代码结构清晰,易于维护。 在C++中,状态模式通常包含以下几个关键...

    JAVA设计模式之行为模式 责任链模式和状态模式

    本篇将探讨两种重要的行为设计模式:责任链模式(Chain of Responsibility Pattern)和状态模式(State Pattern)。 **责任链模式**是一种使多个对象都有机会处理请求的模式,避免请求发送者与接收者之间的耦合。在...

    state模式

    State模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,看起来像是改变了它的类。这种模式常被用于处理具有多种状态的对象,使得对象的状态转换更加清晰,代码更易于理解和维护。 在State模式中,...

    State模式

    "State模式"是一种行为设计模式,它允许对象在内部状态改变时改变其行为,看起来好像对象改变了它的类。这种模式通常用于处理对象的状态变化,使得代码更易于理解和维护。在软件工程中,当一个对象的行为取决于它的...

Global site tag (gtag.js) - Google Analytics