状态模式其意图是在一个对象的状态发生变化时能够同时改变它的行为。一个生活中比较常见的例子就如你(是指你自己本人)在走时时,整个人全身的动作是双手臂前后慢慢摇摆且双脚也是一步一步慢慢往前移的,即:该走路状态下,你所对应的是走路动作;在跑步时,你的双手双脚动作明显频率、步伐都加快,即:在跑步状态下,你所对应的是跑步动作;........;在睡着时,你的全身都是不动的,即:睡着状态下,你是处于睡觉的动作状态。在实际项目开发中,(该模式)最常见的框架设计便是FSM了。模式的类关系结构图参考如下:

编码结构参考如下:

 // the header file
// ----------------------------------------------------------------
#pragma once #include "Framework/Foundation/GFGlobalDefine.h" NSGF_BEGIN template<typename T>
class IGFState; /******************************************************************************
* create : (jacc.kim) [8-18-2015]
* summary : class IGFStateFSM
******************************************************************************/
template<typename T>
class IGFStateFSM
{
public:
typedef T THost; public:
inline THost* getHost(); inline void setHost(THost* pHostObj); public:
virtual ~IGFStateFSM(); protected:
IGFStateFSM(); private:
IGFStateFSM(const IGFStateFSM<THost>&) DELETE_METHOD;
IGFStateFSM& operator=(const IGFStateFSM<THost>&) DELETE_METHOD; private:
THost* m_pHost; };//template<typename T> class IGFStateFSM /******************************************************************************
* create : (jacc.kim) [8-18-2015]
* summary : class IGFState
******************************************************************************/
template<typename T>
class IGFState
{
public:
typedef T THost; public:
inline THost* getHost(); inline void setHost(THost* pHostObj); virtual bool canTrans(); virtual void run(); virtual void enter(); virtual void exit(); public:
virtual ~IGFState(); protected:
IGFState(IGFStateFSM<THost>* pFSM);
IGFState(const IGFState<THost>&) DELETE_METHOD;
IGFState& operator=(const IGFState<THost>&) DELETE_METHOD; IGFStateFSM<THost>* getFSM(); private:
THost* m_pHost;
IGFStateFSM<THost>* m_pFSM; };//template<typename T> class IGFState NSGF_END #include "Framework/Foundation/IGFState.inl" // ----------------------------------------------------------------
// the inl file
// ----------------------------------------------------------------
#include "Framework/Foundation/GFHeader.h" NSGF_BEGIN ///////////////////////////////////////////////////////////////////////////////
// template<typename T> class IGFStateFSM
template<typename T>
nsgf::IGFStateFSM<T>::IGFStateFSM() : m_pHost(nullptr)
{ } template<typename T>
nsgf::IGFStateFSM<T>::~IGFStateFSM() { } template<typename T>
inline typename nsgf::IGFStateFSM<T>::THost* nsgf::IGFStateFSM<T>::getHost() {
return m_pHost;
} template<typename T>
inline void nsgf::IGFStateFSM<T>::setHost(typename THost* pHostObj) {
m_pHost = pHostObj;
} ///////////////////////////////////////////////////////////////////////////////
// template<typename T> class IGFState
template<typename T>
nsgf::IGFState<T>::IGFState(IGFStateFSM<THost>* pFSM) : m_pHost(nullptr)
, m_pFSM(pFSM)
{ } template<typename T>
nsgf::IGFState<T>::~IGFState() { } template<typename T>
inline typename nsgf::IGFState<T>::THost* nsgf::IGFState<T>::getHost() {
return m_pHost;
} template<typename T>
inline void nsgf::IGFState<T>::setHost(typename THost* pHostObj) {
m_pHost = pHostObj;
} template<typename T>
bool nsgf::IGFState<T>::canTrans() {
return false;
} template<typename T>
void nsgf::IGFState<T>::run() {
// some code here........
} template<typename T>
void nsgf::IGFState<T>::enter() {
// some code here........
} template<typename T>
void nsgf::IGFState<T>::exit() {
// some code here........
} template<typename T>
IGFStateFSM<T>* nsgf::IGFState<T>::getFSM() {
return m_pFSM;
} NSGF_END

状态模式编码结构参考

状态模式使得原本是完整体的对象被依据状态切分成多个状态的子模块组合而成,有利也有弊。对于原本就比较复杂,拥有很多状态的对像来说,使用该模式将会使结构更加的清晰,一种状态就对应一个相应的类封装,并且当前某种状态的后续状态也是明确的。特别在对于那些某一时刻,只会存在一个具体状态的对象来说,状态模式可以说是十分完美的。

但也正因为对象被切分成众多的状态集合,也造成了各状态间的交互障碍(因为有时免不了某一状态会依赖于另一状态的某些属性等,毕竟它们都是服务于目标对象),从而在一定程度上破坏了OOP的封装特性。还有更头疼的是对于目标对象来说,如果同一时间要是允许同时存在不止一种状态的话,那就比较悲催。举个例子:游戏中某一角色在遇到敌人时,它可以边躲避敌人的子弹射击,同时可以边向对方射击。这边就至少有两个状态,一是逃跑躲避行为状态;二是向对方射击行为状态。那问题来了,哪个主哪个辅?又或它们并级(别)?再举个例子:某角色被敌方晕住了,同时又被别一个敌人给击飞了(即:被敌人在很敌的时间内,推开很远的距离)。像这边也至少有两种状态。还有更复杂的,多于两种状态同时存在的情况,则情况将是更加复杂的。因此,随着(State模式的)应用越来越广、(遇到的)问题越来越复杂,简单的状态模式设计也逐渐暴露出其弊端。于是后来就有HFMS、BT出现。就个人,还是更推荐BT,感觉这个设计的灵活性会更好些。至于HFMS除了使设计、调试更加复杂外,还是没能完全解决State模式设计的缺陷。

【行为型】State模式的更多相关文章

  1. Java 实现状态(State)模式

    /** * @author stone */ public class WindowState { private String stateValue; public WindowState(Stri ...

  2. 敏捷软件开发(1)--- STATE 模式

    如果状态在运行过程中,不停的切换和改变,我们怎么办? 状态的迁移是我们生活和工程中非常普遍的一个概念.于是在数学上有一种理论来分析和解决这个问题. 有限状态机理论是一个非常成熟的理论,所有动作和流程的 ...

  3. State模式的经典应用场景:订单处理(c#实现)

    State模式在对象内部状态发生变化的时候,改变自身的行为,这通常是通过切换内部状态对象实现的,对象将自身在各个状态的行为推给了状态对象,从而解开了行为与对象的依赖. 场景描述 在经典的订单处理场景中 ...

  4. 无聊之作,RPGdemo制作(一)角色state模式

    今天周末,在家无事可做,不知道为什么,突发奇想,想写一个RPG游戏的demo玩玩.所以就记录一下. 第一步要做的是,为以后的角色类写一个state模式的类,考虑到可能以后会用到,所以用模版来实现, / ...

  5. State模式

    地铁十字转门 状态迁移表格. 起始状态 触发迁移的事件 终止状态  要执行的动作. Locked   Coin               UnLocked UnLock UnLocked Pass  ...

  6. Behavioral模式State模式

    1.意向 同意一个目标,然后改变其内部状态,改变它的行为. 对象似乎改变它的类别. 2.别名 状态对象(Objects for States) 3.动机 考虑一个表示网络连接的类TCPConnecti ...

  7. State 模式

    State模式中我们将状态逻辑和动作实现进行分离.允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类:在一个状态即将结束的时候启用下一个状态. /////////state.h// ...

  8. state模式理解

    state模式应用场景 条件判断很多的情况 比如有很多if else语句:switch case语句等等. 如果以后业务越来越复杂,条件判断有100多个,每种条件的处理逻辑很复杂,不止一个业务逻辑会重 ...

  9. State模式学习笔记

    选用了一个假设需要用户验证的例子进行State模式学习,这个例子并不恰当.无所谓了,只要能学习到其中的内容即可. 适用性: 1,一个对象的行为取决于他的状态,并且它必须在运行时刻依据状态改变他的行为. ...

随机推荐

  1. 动态规划——C编辑最短距离

    C - 编辑距离 时间限制: 1000女士 内存限制: 65536KB 64位输入输出格式: %I64d & %I64u 提交 状态 描述 Let x and y be two strings ...

  2. String Problem - HDU 3374 (kmp+最大最小表示)

    题目大意:有一个字符串长度为N的字符串,这个字符串可以扩展出N个字符串,并且按照顺序编号,比如串  ” SKYLONG “ SKYLONG 1 KYLONGS 2 YLONGSK 3 LONGSKY ...

  3. 遇到的retain cycle例子

    retain cycle 会造成内存溢出,严重情况会引起崩溃.一般注意点也不会发生,但在网络连接比较多的地方就会不小心出现,vc异步的网络请求,成功后的block调用vc,如果此时,用户已经不用此vc ...

  4. 存储的一些基本概念(HBA,LUN)

    有些新手总是在各式各样的概念里绕来绕去,弄的不亦乐乎.所以我就把我的一些理解写了下来,供您参考.我说的不局限于任何一种具体产品和厂家,也可能有些说法和某些厂家的说法不一样,但是我觉得应该算的上是本原的 ...

  5. 怎样把redis编译为库,挪为己用?

    其实这是个伪命题.因为只要正常编译redis,那么在 /deps/hiredis/ 目录下就会生成动态库文件 libhiredis.so. 为了便于学习redis源码,编写一些测试程序,并进行单步跟踪 ...

  6. Java中sleep,wait,yield,join的区别

    sleep() wait() yield() join()用法与区别   1.sleep()方法 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”.不推荐使用. sleep()使当前线程 ...

  7. PHP学习之[第06讲]数组、多维数组和数组函数

    一.数组 ①Array(“aa”,12,true,2.2,”test”,50); ②Array(“title”=>“aa”,  ”age”=>20); 1.创建: $arr= array( ...

  8. android-个性化进度条

    1.案例效果图 2.准备素材                                progress1.png(78*78)              progress2.png(78*78) ...

  9. [Android]如何创建一个View的分割线

    如何创建一个View的分割线,如上图 我们见介绍三种可以创建看起来很不错的view的分割线,如在button之间添加分割线. 这个例子是将为LinearLayout内的三个Button间添加分割线. ...

  10. QT pro文件解析

    在QT中使用qmake自动生成pro文件,如果要自己定制工程选项,则需要自行修改pro文件. pro文件有以下关键字:TEMPLATE.TARGET.DESTDIR.DEPENDPATH.INCLUD ...