当前位置:   article > 正文

js设计模式【详解】—— 状态模式_js 有限状态机

js 有限状态机

目录

状态模式的定义

状态模式的一个模型——有限状态机 Finite-state machine

演示范例1 —— 状态模式实现对话框的显示和隐藏

演示范例2 —— 状态模式实现角色扮演游戏(如魂斗罗)

演示范例3 —— 状态模式实现红绿灯

状态模式的定义

状态模式:当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象。

类型:对象行为型模式

用途:解决系统中复杂对象的状态转换以及不同状态下行为的封装问题

使用场景:

  1. 一个由一个或多个动态变化的属性导致发生不同行为的对象,在与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化,那么这个对象,就是有状态的对象
  2. 代码中包含大量与对象状态有关的条件语句,像是if else或switch case语句,且这些条件执行与否依赖于该对象的状态。

优点:

  1. 一个状态状态对应行为,封装在一个类里,更直观清晰,增改方便
  2. 状态与状态间,行为与行为间彼此独立互不干扰
  3. 避免事物对象本身不断膨胀,条件判断语句过多
  4. 每次执行动作不用走很多不必要的判断语句,用哪个拿哪个

缺点:

  1. 需要将事物的不同状态以及对应的行为拆分出来,有时候会无法避免的拆分的很细,有的时候涉及业务逻辑,一个动作拆分出对应的两个状态,动作就拆不明白了,过度设计
  2. 必然会增加事物类和动作类的个数,有时候动作类再根据单一原则,按照功能拆成几个类,会反而使得代码混乱,可读性降低

状态模式的一个模型——有限状态机 Finite-state machine

 日常开发中很多具有多种状态的对象,都可以用有限状态机模型来模拟,一般都具有以下特点:

  1. 事物拥有多种状态,任一时间只会处于一种状态不会处于多种状态;
  2. 动作可以改变事物状态,一个动作可以通过条件判断,改变事物到不同的状态,但是不能同时指向多个状态,一个时间,就一个状态
  3. 状态总数是有限的;

github上有一个有限状态机的函数库javascript-state-machine,可以了解一下

https://github.com/jakesgordon/javascript-state-machine

演示范例1 —— 状态模式实现对话框的显示和隐藏

  1. var Dialog = function(){
  2. var _state = null;
  3. this.setState = function(state){
  4. _state = state;
  5. }
  6. this.getState = function(){
  7. return _state;
  8. }
  9. }
  10. var ShowState = function(){
  11. this.doAction = function(dialog){
  12. console.log("对Dialog设置显示状态:");
  13. dialog.setState(this);
  14. }
  15. this.toString = function(){
  16. console.log("显示中......");
  17. }
  18. }
  19. var HideState = function(){
  20. this.doAction = function(dialog){
  21. console.log("对Dialog设置隐藏状态:");
  22. dialog.setState(this);
  23. }
  24. this.toString = function(){
  25. console.log("已隐藏......");
  26. }
  27. }
  28. var dialog = new Dialog();
  29. var showState = new ShowState();
  30. var hideState = new HideState();
  31. showState.doAction(dialog);
  32. //对Dialog设置显示状态:
  33. dialog.getState().toString();
  34. //显示中......
  35. hideState.doAction(dialog);
  36. //对Dialog设置隐藏状态
  37. dialog.getState().toString();
  38. //已隐藏......

例子里Dialog对象有两种状态,显示和隐藏,我把两种状态提取出来,使得状态的管理更加灵活。在这个例子里面Dialog称之为环境类,环境类又称为上下文类,他拥有多种状态。环境类内部需要维护一个state对象用来定义当前状态。HideState,ShowState称之为状态类,对应环境类的一个具体状态,toString称之为状态类的行为,每一个状态类的行为都有所不同。

演示范例2 —— 状态模式实现角色扮演游戏(如魂斗罗)

  1. class Contra {
  2. constructor () {
  3. //存储当前待执行的动作 们
  4. this._currentstate = {};
  5. }
  6. //添加动作
  7. changeState (){
  8. //清空当前的动作集合
  9. this._currentstate = {};
  10. //遍历添加动作
  11. Object.keys(arguments).forEach(
  12. (i) => this._currentstate[arguments[i]] = true
  13. )
  14. return this;
  15. }
  16. //执行动作
  17. contraGo (){
  18. //当前动作集合中的动作依次执行
  19. Object.keys(this._currentstate).forEach(
  20. (k) => Actions[k] && Actions[k].apply(this)
  21. )
  22. return this;
  23. }
  24. };
  25. const Actions = {
  26. up : function(){
  27. //向上跳
  28. console.log('up');
  29. },
  30. down : function(){
  31. //趴下
  32. console.log('down');
  33. },
  34. forward : function(){
  35. //向前跑
  36. console.log('forward');
  37. },
  38. backward : function(){
  39. //往老家跑
  40. console.log('backward');
  41. },
  42. shoot : function(){
  43. //开枪吧
  44. console.log('shoot');
  45. },
  46. };
  47. var littlered = new Contra();
  48. littlered.changeState('shoot','up').contraGo();

控制台会输出: shoot up

状态模式,将条件判断的结果转化为状态对象内部的状态(代码中的up,down,backward,forward),内部状态通常作为状态对象内部的私有变量(this._currentState),然后提供一个能够调用状态对象内部状态的接口方法对象(changeState,contraGo),这样对状态的改变,对状态方法的调用的修改和增加也会很容易,方便了对状态对象中内部状态的管理。

同时,状态模式将每一个条件分支放入一个独立的类中,也就是代码中的Actions。这使得你可以根据对象自身的情况将对象的状态(动作——up,down,backward,forward)作为一个对象(Actions.up,Actions.down这样),这一对象可以不依赖于其他对象而独立变化(一个行为一个动作,互不干扰)。

可以看出,状态模式就是一种适合多种状态场景下的设计模式,改写之后代码更加清晰,提高代码的维护性和扩展性,不用再牵一发动全身

演示范例3 —— 状态模式实现红绿灯

  1. var trafficLight = (function () {
  2. var currentLight = null;
  3. return {
  4. change: function (light) {
  5. currentLight = light;
  6. currentLight.go();
  7. }
  8. }
  9. })();
  10. function RedLight() { }
  11. RedLight.prototype.go = function () {
  12. console.log("this is red light");
  13. }
  14. function GreenLight() { }
  15. GreenLight.prototype.go = function () {
  16. console.log("this is green light");
  17. }
  18. function YellowLight() { }
  19. YellowLight.prototype.go = function () {
  20. console.log("this is yellow light");
  21. }
  22. trafficLight.change(new RedLight());
  23. trafficLight.change(new YellowLight());

trafficLight是一个红绿灯的实例,传入一个构造函数,对象暴露change方法改变内部状态,也就是灯的颜色,change接收的同样是一个状态的对象,调用对象的方法触发响应的动作,这里的动作都叫go,不同颜色的灯对象有着不同的go的实现。

通过传入灯对象到change方法中,从而改变红绿灯的状态,触发其相应的处理程序,这就是一个典型的状态模式的应用。

更多设计模式详见——js设计模式【详解】总目录
https://blog.csdn.net/weixin_41192489/article/details/116154815

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/696574
推荐阅读
相关标签
  

闽ICP备14008679号