Arthur: Yu, Tao
有限状态机,下面的例子中对状态类使用了Singleton模式,因为各个目标类的对象(智能体)共享状态类的唯一实例,可消除状态每次改变时分配和
释放内存的需要.如果有很多目标类对象共享一个复杂的FSM,这是非常必要的.
但是对状态类使用Singleton模式的前提是使用状态类实例的类的对象自身不需要访问大量的外部数据。
1.定义一个状态类共同的虚基类
class Troll;
class State
{
public:
virtual ~State(){};
virtual void Enter (Troll* )=0;
virtual void Execute (Troll*)=0;
virtual void Exit (Troll*)=0;
};
2.定义将使用状态类的目标类
---Troll.h
class Troll
{
public:
void Update();
void ChangeState(State* m_pNewState);
private:
static State* m_pCurrentState;
省略属性接口;
};
---Troll.cpp
void Troll::Update()
{
if(m_pCurrentState;)
{(m_pCurrentState->Execute(this);}
}
void Troll::ChangeState(State* m_pNewState)
{
assert (m_pCurrentState && pNewState); //调用两个状态的方法前确认两个状态都是有效的
m_pCurrentState->Exit(this);
m_pCurrentState=m_pNewState;
m_pCurrentState->Enter(this);
}
---定义具体状态类
---.h
class State_A: public State
{
private:
State_A(){};
State_A(const State_A&);
public:
static State_A* Instance();
void Enter(Troll* troll)
{
if(troll->trollownsfunctionA())
{
状态进入时执行的动作;
}
}
void Execute(Troll* troll)
{
if(troll->trollownsfunctionB())
{
troll->ChangeState(State_B::Instance()); --这里调用Instance得到一个指向状态B的单一静态实例的指针作为参数传入Troll的ChangeState函数.
}
}
void Exit(Troll* troll)
{
if(troll->trollownsfunctionC())
{
状态退出时执行的动作;
}
}
};
class State_B : public State
{
private:
State_B(){};
State_B(const State_B&);
public:
static State_B* Instance();
void Enter(Troll* troll)
{
if(troll->trollownsfunctionD())
{
状态进入时执行的动作;
}
}
void Execute(Troll* troll)
{
if(troll->trollownsfunctionE())
{
troll->ChangeState(State_A::Instance()); --这里调用Instance得到一个指向状态A的单一静态实例的指针作为参数传入Troll的ChangeState函数.
}
}
void Exit(Troll* troll)
{
if(troll->trollownsfunctionF())
{
状态退出时执行的动作;
}
}
};
---Singelton模式中调用私有构造函数的公有函数的定义必须放在.cpp文件中,如放在头文件中则每个包含该头文件的cpp文件中都会创建一个实例。
---.cpp
static State_A* State_A::Instance()
{
static State_A instance;
return &instance;
}
static State_B* State_B::Instance()
{
static State_B instance;
return &instance;
}