1、定义
在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
2、介绍
优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点: 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
使用场景: 1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。
注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
3、源码
类关系图:
3.1、头文件
ILift.h
#pragma once
#include<iostream>
using namespace std;
class ILift
{
public:
ILift(void)
{
}
virtual ~ILift(void)
{
}
static const int OPENING_STATE = 1;
static const int CLOSING_STATE = 2;
static const int RUNNING_STATE = 3;
static const int STOPPING_STATE = 4;
virtual void SetState(int state) = 0;
virtual void Open() = 0;
virtual void Close() = 0;
virtual void Run() = 0;
virtual void Stop() = 0;
};
Lift.h
#pragma once
#include "ilift.h"
class CLift :
public ILift
{
public:
CLift(void);
~CLift(void);
void SetState(int state);
void Open();
void Close();
void Run();
void Stop();
private:
int m_state;
void OpenWithoutLogic();
void CloseWithoutLogic();
void RunWithoutLogic();
void StopWithoutLogic();
};
LiftState.h
#pragma once
class CContext;
class CLiftState
{
public:
CLiftState(void);
virtual ~CLiftState(void);
void SetContext(CContext *pContext);
virtual void Open() = 0;
virtual void Close() = 0;
virtual void Run() = 0;
virtual void Stop() = 0;
protected:
CContext *m_pContext;
};
CloseingState.h
#pragma once
#include "liftstate.h"
class CCloseingState :
public CLiftState
{
public:
CCloseingState(void);
~CCloseingState(void);
void Open();
void Close();
void Run();
void Stop();
};
OpenningState.h
#pragma once
#include "liftstate.h"
class COpenningState :
public CLiftState
{
public:
COpenningState(void);
~COpenningState(void);
void Open();
void Close();
void Run();
void Stop();
};
RunningState.h
#pragma once
#include "liftstate.h"
class CRunningState :
public CLiftState
{
public:
CRunningState(void);
~CRunningState(void);
void Open();
void Close();
void Run();
void Stop();
};
StoppingState.h
#pragma once
#include "liftstate.h"
class CStoppingState :
public CLiftState
{
public:
CStoppingState(void);
~CStoppingState(void);
void Open();
void Close();
void Run();
void Stop();
};
Contex.h
#pragma once
#include "LiftState.h"
#include "OpenningState.h"
#include "CloseingState.h"
#include "RunningState.h"
#include "StoppingState.h"
class CContext
{
public:
CContext(void);
~CContext(void);
static COpenningState *pOpenningState;
static CCloseingState *pCloseingState;
static CRunningState *pRunningState;
static CStoppingState *pStoppingState;
CLiftState * GetLiftState();
void SetLiftState(CLiftState *pLiftState);
void Open();
void Close();
void Run();
void Stop();
private:
CLiftState *m_pLiftState;
};
3.2、实现
Lift.cpp
#include "Lift.h"
CLift::CLift(void)
{
this->m_state = 0;
}
CLift::~CLift(void)
{
}
void CLift::SetState(int state)
{
this->m_state = state;
}
void CLift::Open()
{
switch(this->m_state)
{
case OPENING_STATE:
break;
case CLOSING_STATE:
this->OpenWithoutLogic();
this->SetState(OPENING_STATE);
break;
case RUNNING_STATE:
break;
case STOPPING_STATE:
this->OpenWithoutLogic();
this->SetState(OPENING_STATE);
break;
}
}
void CLift::Close()
{
switch(this->m_state)
{
case OPENING_STATE:
this->CloseWithoutLogic();
this->SetState(CLOSING_STATE);
break;
case CLOSING_STATE:
break;
case RUNNING_STATE:
break;
case STOPPING_STATE:
break;
}
}
void CLift::Run()
{
switch(this->m_state)
{
case OPENING_STATE:
break;
case CLOSING_STATE:
this->RunWithoutLogic();
this->SetState(RUNNING_STATE);
break;
case RUNNING_STATE:
break;
case STOPPING_STATE:
this->RunWithoutLogic();
this->SetState(RUNNING_STATE);
break;
}
}
void CLift::Stop()
{
switch(this->m_state)
{
case OPENING_STATE:
break;
case CLOSING_STATE:
this->StopWithoutLogic();
this->SetState(CLOSING_STATE);
break;
case RUNNING_STATE:
this->StopWithoutLogic();
this->SetState(CLOSING_STATE);
break;
case STOPPING_STATE:
break;
}
}
void CLift::OpenWithoutLogic()
{
cout << "电梯门开启..." << endl;
}
void CLift::CloseWithoutLogic()
{
cout << "电梯门关闭..." << endl;
}
void CLift::RunWithoutLogic()
{
cout << "电梯上下跑起来..." << endl;
}
void CLift::StopWithoutLogic()
{
cout << "电梯停止了..." << endl;
}
LiftState.cpp
#include "LiftState.h"
CLiftState::CLiftState(void)
{
}
CLiftState::~CLiftState(void)
{
}
void CLiftState::SetContext( CContext *pContext )
{
m_pContext = pContext;
}
CloseingState.cpp
#include "CloseingState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;
CCloseingState::CCloseingState(void)
{
}
CCloseingState::~CCloseingState(void)
{
}
void CCloseingState::Open()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pOpenningState);
this->CLiftState::m_pContext->GetLiftState()->Open();
}
void CCloseingState::Close()
{
cout << "电梯门关闭..." << endl;
}
void CCloseingState::Run()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pRunningState);
this->CLiftState::m_pContext->GetLiftState()->Run();
}
void CCloseingState::Stop()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pStoppingState);
this->CLiftState::m_pContext->GetLiftState()->Stop();
}
OpenningState.cpp
#include "OpenningState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;
COpenningState::COpenningState(void)
{
}
COpenningState::~COpenningState(void)
{
}
void COpenningState::Open()
{
cout << "电梯门开启..." << endl;
}
void COpenningState::Close()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pCloseingState);
this->CLiftState::m_pContext->GetLiftState()->Close();
}
void COpenningState::Run()
{
//do nothing
}
void COpenningState::Stop()
{
//do nothing
}
RunningState.cpp
#include "RunningState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;
CRunningState::CRunningState(void)
{
}
CRunningState::~CRunningState(void)
{
}
void CRunningState::Open()
{
//do nothing
}
void CRunningState::Close()
{
//do nothing
}
void CRunningState::Run()
{
cout << "电梯上下跑..." << endl;
}
void CRunningState::Stop()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pStoppingState);
this->CLiftState::m_pContext->GetLiftState()->Stop();
}
StoppingState.cpp
#include "StoppingState.h"
#include "Context.h"
CStoppingState::CStoppingState(void)
{
}
CStoppingState::~CStoppingState(void)
{
}
void CStoppingState::Open()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pOpenningState);
this->CLiftState::m_pContext->GetLiftState()->Open();
}
void CStoppingState::Close()
{
//do nothing
}
void CStoppingState::Run()
{
this->CLiftState::m_pContext->SetLiftState(CContext::pRunningState);
this->CLiftState::m_pContext->GetLiftState()->Run();
}
void CStoppingState::Stop()
{
cout << "电梯停止了..." << endl;
}
Context.cpp
#include"Contex.h"
#include<iostream>
using namespace std;
COpenningState* CContext::pOpenningState = NULL;
CCloseingState* CContext::pCloseingState = NULL;
CRunningState* CContext::pRunningState = NULL;
CStoppingState* CContext::pStoppingState = NULL;
CContext::CContext(void)
{
m_pLiftState = NULL;
pOpenningState = new COpenningState();
pCloseingState = new CCloseingState();
pRunningState = new CRunningState();
pStoppingState = new CStoppingState();
}
CContext::~CContext(void)
{
delete pOpenningState;
pOpenningState = NULL;
delete pCloseingState;
pCloseingState = NULL;
delete pRunningState;
pRunningState = NULL;
delete pStoppingState;
pStoppingState = NULL;
}
CLiftState * CContext::GetLiftState()
{
return m_pLiftState;
}
//void CContext::SetLiftState(CLiftState *pLiftState)
{
this->m_pLiftState = pLiftState;
this->m_pLiftState->SetContext(this);
}
void CContext::Open()
{
//m_pLiftState指针指向CCloseingState
this->m_pLiftState->Open();
//执行完后m_pLiftState指针指向COpenningState
}
void CContext::Close()
{
//m_pLiftState指针指向CCloseingState
this->m_pLiftState->Close();//调用CloseingState的Close方法
//执行完后m_pLiftState指针指向COpenningState
}
void CContext::Run()
{
//m_pLiftState指针指向COpenningState
this->m_pLiftState->Run();
//执行完后m_pLiftState指针指向CRunningState
}
void CContext::Stop()
{
//m_pLiftState指针指向CRunningState
this->m_pLiftState->Stop();
//执行完后m_pLiftState指针指向CStoppingState
}
State.cpp
#include "ILift.h"
#include "Lift.h"
#include"Contex.h"
#include "OpenningState.h"
#include "CloseingState.h"
#include "RunningState.h"
#include "StoppingState.h"
#include <iostream>
using std::cout;
using std::endl;
void DoIt()
{
ILift *pLift = new CLift();//基类指针指向子类对象,调用子类的方法.
pLift->SetState(ILift::STOPPING_STATE);//电梯的初始条件是停止状态。
//对具体执行动作设置为私有方法,通过类的公有方法,判段具体执行的动作
pLift->Open();//首先是电梯门开启,人进去
pLift->Close();//然后电梯门关闭
pLift->Run();//再然后,电梯跑起来,向上或者向下
pLift->Stop();//最后到达目的地,电梯停下来
delete pLift;
}
void DoNew()
{
CContext context;
CCloseingState closeingState;
context.SetLiftState(&closeingState);
context.Close();
context.Open();
context.Run();
context.Stop();
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << "----------使用模式之前----------" << endl;
DoIt();
cout << "----------使用模式之后----------" << endl;
DoNew();
system(“pause”)
return 0;
}
4、结果
参考文献:《菜鸟教程》 https://blog.csdn.net/phiall/article/details/52199659博客