c设计模式学习状态模式

状态模式,优点:多个状态工作分明,需要添加新状态的时候,少量修改就可以完成。缺点:状态子类太多。

文章来源:C++技术网原创文章版权所有,未经授权,禁止转载。

  状态模式在很多书籍都会涉及到,我也曾经看过,发现很简单,然后就没有实际实现一次。后来想在状态模式下实现《扭蛋机》的时候,发现一些难点,特别是C++这类内存需要自己管理的语言,实现起来时有点困难的。

  首先我们看一下状态模式的模型

  

  状态类state里面的每一个行为都要传入当前行为,代理类调用它所指向的行为的时候,要传入this(自己),这个传入自己是为了在一个状态里面可以跳跃到另外一个状态。

  例如

//当前状态是状态1void行为1(proxy*now){if(符合状态3条件){deletenow-_now;now-_now=new状态3();now-_now-行为1();//因为自己没有执行该行为,所以交给状态3}}

  我们从代码里面可以看到

deletenow-_now;//删除自己

有些同学会问,为什么now-_now就是删除自己?

  

  因为目前的状态是状态1,代理类里面的_now指针是指向状态1的,而执行void行为1()的时候就是调用状态1的行为1,delete代理类里面_now指针就是delete自己。

  状态1-行为1()这个函数删除了状态1,看起来是不是很难明白?这就对了,难点在于,删除了自己以后,自己的成员函数已经全部释放了,下一步必须交给下一个状态来做这个行为1()

  所以下一步必须是

  

now-_now-行为1();//因为自己没有执行该行为,所以交给状态3

  这个就是注意点

  千万不要再调用成员变量或者成员函数,否则都是无效或者崩溃。

  

  然而我们看上图的状态模式实现,不难发现,每一个状态都需要传入当前代理,如vitrualvoid行为1(proxy*当前行为);

  这个的参数会令人感到厌倦。所以我们会做个构造函数,在构造的时候就直接获取这个指针

  如

  

classState{public:State(proxy*proxy_in):proxy(proxy_in){}行为1();行为2();行为3();private:proxy*_proxy;};

  

  这样我们就不用在每一个成员函数都传进去一个指针了。

  然而这个做法是有缺陷的。

  这里有同学就起哄了,为什么你刚刚提出了这个方案,又立刻否决了,能不能爽点?

  我,我,我,只是想引导你们嘛~~

  我们再看一段代码

  

//当前的状态为状态1void行为1(){if(符合状态3条件){delete_proxy-_now;_proxy-_now=new状态3();_proxy-_now-行为1();//因为自己没有执行该行为,所以交给状态3}}

  

  同学们仔细看看,delete_proxy-_now;以后会怎么样?成员变量_proxy,这个指针还有效吗?

  很明显类都被删除了,成员变量被释放,_proxy想当然地变成了野指针,也许碰巧的你再使用还可以。但是理论上或者debug版上做这个动作,_proxy已经变成(0xcdcdcdcdor0xccccccc)这样了。

  那么我们怎么办才能办呢?

  

proxy*temp=_proxy;deletetemp-_now;temp-_now=new状态3();temp-_now-行为1();//因为自己没有执行该行为,所以交给状态3

我目前只能想到这样的解决方案了。(如果有更好的方法,请留言);

  

  还是原来的注意点,delete当前状态以后,不要继续使用成员变量了。这个需要维护者小心翼翼的写代码。

  然而,具有托管,垃圾回收机制的语言很可能不存在这个问题。

  

  说了这么多,给出我的版本

  

  

  有一个接口action来规范,代理类只能做代理的作用。state类构造的时候要传入两个参数,一个是代理状态的,一个是要处理的数据。

  

  有些同学就会问了。能不能把状态更换的方法交给代理类或者一个管理者来处理,而不要自己做delete释放工作,这样的话是不是更好?

  其实看图的时候我也做了相应的保留,例如setstate的时候把当前状态放到_lastSta指针里,把要更换的新状态放到_sta里,在下一次切换的时候,再删除_lastSta;这样做也许是能防止成员变量被无效的问题,但是也会产生一些新问题,例如明明我上一个状态已经切换了,它还存在呢,我是做了计数的,这样会妨碍到我~~~~之类的问题。

  

  我看到过一些状态模式是一开始把所有状态都实例化,作为成员变量,然后切换模式的时候就只更改指针,而不进行删除工作,这个也算是一总解决方案,但是状态之间的可控就会降低一些。因为可能会出现未切换状态就调用了其他状态的函数的情况。

  

  希望大家能,动手多实践,学到了东西就分享分享,谢谢各位~~

文章来源:C++技术网原创文章版权所有,未经授权,禁止转载。









































?北京哪家白癜风医院治疗好
?北京看白癜风比较好专科医院



转载请注明:http://www.nydjfy.com/bcxx/1330.html

  • 上一篇文章:
  •   
  • 下一篇文章: