[行为模式] state模式

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

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

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

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


下面的部分请看以下链接[url]http://blog.csdn.net/hguisu/article/details/7557252[/url]

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值