以下摘自【设计模式精解(GoF 23种设计解析附C++实现源码)】中关于状态机模式的介绍
有限状态自动机(FSM)也是一个典型的状态不同,对输入有不同的响应(状态转移)。通常我们在实现这类系统会使用到很多的Switch/Case语句,Case某种状态,发生什么动作,Case另外一种状态,则发生另外一种状态。但是这种实现方式至少有以下两个问题:
1)当状态数目不是很多的时候,Switch/Case可能可以搞定。但是当状态数目很多的时候(实际系统中也正是如此),维护一大组的Switch/Case语句将是一件异常困难并且容易出错的事情。
2)状态逻辑和动作实现没有分离。在很多的系统实现中,动作的实现代码直接写在状态的逻辑当中。这带来的后果就是系统的扩展性和维护得不到保证。
State模式就是被用来解决上面列出的两个问题的,在State模式中我们将状态逻辑和动作实现进行分离。当一个操作中要维护大量的case分支语句,并且这些分支依赖于对象的状态。State模式将每一个分支都封装到独立的类中。
在这里【设计模式精解(GoF 23种设计解析附C++实现源码)】中的代码那样,我只是解释一个模型,实现一个模型,用栈来管理游戏状态。你可以称呼它为游戏状态管理栈等。
说明:
由于考虑到游戏中的状态管理一般只有一个,故这里采用单键模式模型。
由于考虑到会增加复杂度,这里不考虑模板(按道理应该采用模板,以增加代码可重用性,当然,用了模板就不再是纯单键模式了)
好了,老样子,上代码
先看看定义代码
头文件STATEMANAGER.H
1//********************************************************************
2// STATEMANAGER.H 文件注释
3// 文件名 : STATEMANAGER.H
4// 文件路径: J:/CODING/游戏引擎/STATEMANAGER/
5// 作者 : RIPPLE
6// 创建时间: 2009/10/3 13:44
7// 文件描述: 游戏状态管理栈类声明
8//*********************************************************************
9
10#ifndef _H_STATEMANGER_H_
11#define _H_STATEMANGER_H_
12namespace ripple
13{
14 //********************************************************************
15 // CStateManager 类注释
16 // 类名 : CStateManager
17 // 基类名称: NULL
18 // 命名空间: ripple
19 // 作者 : RIPPLE
20 // 创建时间: 2009/10/3 13:45
21 // 类描述 : 游戏状态管理类。一般游戏只会有一个状态管理,故采用单键模式管理
22 //*********************************************************************
23
24 class CStateManager
25 {
26 public:
27 static CStateManager& getSingleton(); //返回引用,这步至关重要。
28 static CStateManager* getSingletonPtr(); //返回单键指针
29
30 virtual ~CStateManager();
31
32 //定义状态调用函数指针类型
33 typedef void (*StateCallFunc)();
34
35 //定义状态结构
36 typedef struct tagState
37 {
38 tagState()
39 {
40 this->Update = NULL;
41 this->Next = NULL;
42 }
43 StateCallFunc Update; //各个状态调用的函数指针
44 tagState* Next; //下个函数状态的地址(如果有的话)
45 }STATE;
46
47 void Push(StateCallFunc func); //插入一个状态
48 BOOL Pop(); //弹出一个状态
49 BOOL Process(); //执行栈顶状态的更新函数
50
51 private:
52 CStateManager();
53 STATE* mp_TopState;
54 static CStateManager* ms_Singleton;
55 };
56
57}
58#endif
2// STATEMANAGER.H 文件注释
3// 文件名 : STATEMANAGER.H
4// 文件路径: J:/CODING/游戏引擎/STATEMANAGER/
5// 作者 : RIPPLE
6// 创建时间: 2009/10/3 13:44
7// 文件描述: 游戏状态管理栈类声明
8//*********************************************************************
9
10#ifndef _H_STATEMANGER_H_
11#define _H_STATEMANGER_H_
12namespace ripple
13{
14 //********************************************************************
15 // CStateManager 类注释
16 // 类名 : CStateManager
17 // 基类名称: NULL
18 // 命名空间: ripple
19 // 作者 : RIPPLE
20 // 创建时间: 2009/10/3 13:45
21 // 类描述 : 游戏状态管理类。一般游戏只会有一个状态管理,故采用单键模式管理
22 //*********************************************************************
23
24 class CStateManager
25 {
26 public:
27 static CStateManager& getSingleton(); //返回引用,这步至关重要。
28 static CStateManager* getSingletonPtr(); //返回单键指针
29
30 virtual ~CStateManager();
31
32 //定义状态调用函数指针类型
33 typedef void (*StateCallFunc)();
34
35 //定义状态结构
36 typedef struct tagState
37 {
38 tagState()
39 {
40 this->Update = NULL;
41 this->Next = NULL;
42 }
43 StateCallFunc Update; //各个状态调用的函数指针
44 tagState* Next; //下个函数状态的地址(如果有的话)
45 }STATE;
46
47 void Push(StateCallFunc func); //插入一个状态
48 BOOL Pop(); //弹出一个状态
49 BOOL Process(); //执行栈顶状态的更新函数
50
51 private:
52 CStateManager();
53 STATE* mp_TopState;
54 static CStateManager* ms_Singleton;
55 };
56
57}
58#endif
对应的实现,源文件STATEMANAGER.CPP
1//********************************************************************
2// STATEMANAGER.CPP 文件注释
3// 文件名 : STATEMANAGER.CPP
4// 文件路径: J:/CODING/游戏引擎/STATEMANAGER/
5// 作者 : RIPPLE
6// 创建时间: 2009/10/3 13:47
7// 文件描述: CSteteManager游戏状态管理类实现
8//*********************************************************************
9
10#include <windows.h>
11#include "StateManager.h"
12//引用ripple命名空间
13using namespace ripple;
14//初始化静态指针
15CStateManager* CStateManager::ms_Singleton = NULL;
16//返回单键引用,必须返回引用,否则,会在返回时复制一次对象,将导致出错
17CStateManager& CStateManager::getSingleton()
18{
19 if (NULL == CStateManager::ms_Singleton)
20 {
21 new CStateManager();
22 }
23 return *CStateManager::ms_Singleton;
24}
25//返回单键指针
26CStateManager* CStateManager::getSingletonPtr()
27{
28 if (NULL == CStateManager::ms_Singleton)
29 {
30 new CStateManager();
31 }
32 return CStateManager::ms_Singleton;
33}
34//构造函数
35CStateManager::CStateManager()
36{
37 this->mp_TopState = NULL;
38 CStateManager::ms_Singleton = this;
39}
40//析构函数
41CStateManager::~CStateManager()
42{
43 STATE* tmp;
44 while ((tmp = this->mp_TopState) != NULL)
45 {
46 this->mp_TopState = this->mp_TopState->Next;
47 delete tmp;
48 }
49 if (NULL != CStateManager::ms_Singleton)
50 {
51 delete CStateManager::ms_Singleton;
52 CStateManager::ms_Singleton = NULL;
53 }
54}
55//插入一个状态
56void CStateManager::Push(StateCallFunc func)
57{
58 if(NULL != func)
59 {
60 STATE* tmp = new STATE;
61 tmp->Next = this->mp_TopState;
62 tmp->Update = func;
63 this->mp_TopState = tmp;
64 }
65}
66//弹出一个状态
67BOOL CStateManager::Pop()
68{
69 STATE* tmp = this->mp_TopState;
70 if (NULL != tmp)
71 {
72 this->mp_TopState = this->mp_TopState->Next;
73 delete tmp;
74 }
75
76 if (NULL == this->mp_TopState)
77 {
78 return FALSE;
79 }
80
81 return TRUE;
82}
83//执行栈顶状态的更新函数
84BOOL CStateManager::Process()
85{
86 if (NULL != this->mp_TopState)
87 {
88 this->mp_TopState->Update();
89 return TRUE;
90 }
91 return FALSE;
92}
2// STATEMANAGER.CPP 文件注释
3// 文件名 : STATEMANAGER.CPP
4// 文件路径: J:/CODING/游戏引擎/STATEMANAGER/
5// 作者 : RIPPLE
6// 创建时间: 2009/10/3 13:47
7// 文件描述: CSteteManager游戏状态管理类实现
8//*********************************************************************
9
10#include <windows.h>
11#include "StateManager.h"
12//引用ripple命名空间
13using namespace ripple;
14//初始化静态指针
15CStateManager* CStateManager::ms_Singleton = NULL;
16//返回单键引用,必须返回引用,否则,会在返回时复制一次对象,将导致出错
17CStateManager& CStateManager::getSingleton()
18{
19 if (NULL == CStateManager::ms_Singleton)
20 {
21 new CStateManager();
22 }
23 return *CStateManager::ms_Singleton;
24}
25//返回单键指针
26CStateManager* CStateManager::getSingletonPtr()
27{
28 if (NULL == CStateManager::ms_Singleton)
29 {
30 new CStateManager();
31 }
32 return CStateManager::ms_Singleton;
33}
34//构造函数
35CStateManager::CStateManager()
36{
37 this->mp_TopState = NULL;
38 CStateManager::ms_Singleton = this;
39}
40//析构函数
41CStateManager::~CStateManager()
42{
43 STATE* tmp;
44 while ((tmp = this->mp_TopState) != NULL)
45 {
46 this->mp_TopState = this->mp_TopState->Next;
47 delete tmp;
48 }
49 if (NULL != CStateManager::ms_Singleton)
50 {
51 delete CStateManager::ms_Singleton;
52 CStateManager::ms_Singleton = NULL;
53 }
54}
55//插入一个状态
56void CStateManager::Push(StateCallFunc func)
57{
58 if(NULL != func)
59 {
60 STATE* tmp = new STATE;
61 tmp->Next = this->mp_TopState;
62 tmp->Update = func;
63 this->mp_TopState = tmp;
64 }
65}
66//弹出一个状态
67BOOL CStateManager::Pop()
68{
69 STATE* tmp = this->mp_TopState;
70 if (NULL != tmp)
71 {
72 this->mp_TopState = this->mp_TopState->Next;
73 delete tmp;
74 }
75
76 if (NULL == this->mp_TopState)
77 {
78 return FALSE;
79 }
80
81 return TRUE;
82}
83//执行栈顶状态的更新函数
84BOOL CStateManager::Process()
85{
86 if (NULL != this->mp_TopState)
87 {
88 this->mp_TopState->Update();
89 return TRUE;
90 }
91 return FALSE;
92}
测试代码 TEST.CPP
1//**********************************************************