状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来是改变了其类。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

既然状态者模式是对已有对象的状态进行抽象,则自然就有抽象状态者类和具体状态者类,而原来已有对象需要保存抽象状态者类的引用,通过调用抽象状态者的行为来改变已有对象的行为。经过上面的分析,状态者模式的结构图也就很容易理解了,具体结构图如下图示。

从上图可知,状态者模式涉及以下三个角色:

  • Account类:维护一个State类的一个实例,该实例标识着当前对象的状态。
  • State类:抽象状态类,定义了一个具体状态类需要实现的行为约定。
  • SilveStater、GoldState和RedState类:具体状态类,实现抽象状态类的每个行为。

C#状态模式:

  1. namespace 状态模式
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. //紧急项目
  8. Work emergencyProjects = new Work();
  9. emergencyProjects.Hour = ;
  10. emergencyProjects.WriteProgram();
  11. emergencyProjects.Hour = ;
  12. emergencyProjects.WriteProgram();
  13. emergencyProjects.Hour = ;
  14. emergencyProjects.WriteProgram();
  15. emergencyProjects.Hour = ;
  16. emergencyProjects.WriteProgram();
  17. emergencyProjects.Hour = ;
  18. emergencyProjects.WriteProgram();
  19. emergencyProjects.Hour = ;
  20.  
  21. //emergencyProjects.WorkFinished = true;
  22. emergencyProjects.TaskFinished = false;
  23.  
  24. emergencyProjects.WriteProgram();
  25. emergencyProjects.Hour = ;
  26. emergencyProjects.WriteProgram();
  27. emergencyProjects.Hour = ;
  28. emergencyProjects.WriteProgram();
  29.  
  30. Console.Read();
  31. }
  32. }
  33.  
  34. //抽象状态
  35. public abstract class State
  36. {
  37. public abstract void WriteProgram(Work w);
  38. }
  39.  
  40. //上午工作状态
  41. public class ForenoonState : State
  42. {
  43. public override void WriteProgram(Work w)
  44. {
  45. if (w.Hour < )
  46. {
  47. Console.WriteLine("当前时间:{0}点 上午工作,精神百倍", w.Hour);
  48. }
  49. else
  50. {
  51. w.SetState(new NoonState());
  52. w.WriteProgram();
  53. }
  54. }
  55. }
  56.  
  57. //中午工作状态
  58. public class NoonState : State
  59. {
  60. public override void WriteProgram(Work w)
  61. {
  62. if (w.Hour < )
  63. {
  64. Console.WriteLine("当前时间:{0}点 饿了,午饭;犯困,午休。", w.Hour);
  65. }
  66. else
  67. {
  68. w.SetState(new AfternoonState());
  69. w.WriteProgram();
  70. }
  71. }
  72. }
  73.  
  74. //下午工作状态
  75. public class AfternoonState : State
  76. {
  77. public override void WriteProgram(Work w)
  78. {
  79. if (w.Hour < )
  80. {
  81. Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", w.Hour);
  82. }
  83. else
  84. {
  85. w.SetState(new EveningState());
  86. w.WriteProgram();
  87. }
  88. }
  89. }
  90.  
  91. //晚间工作状态
  92. public class EveningState : State
  93. {
  94. public override void WriteProgram(Work w)
  95. {
  96. if (w.TaskFinished)
  97. {
  98. w.SetState(new RestState());
  99. w.WriteProgram();
  100. }
  101. else
  102. {
  103. if (w.Hour < )
  104. {
  105. Console.WriteLine("当前时间:{0}点 加班哦,疲累之极", w.Hour);
  106. }
  107. else
  108. {
  109. w.SetState(new SleepingState());
  110. w.WriteProgram();
  111. }
  112. }
  113. }
  114. }
  115.  
  116. //睡眠状态
  117. public class SleepingState : State
  118. {
  119. public override void WriteProgram(Work w)
  120. {
  121. Console.WriteLine("当前时间:{0}点 不行了,睡着了。", w.Hour);
  122. }
  123. }
  124.  
  125. //下班休息状态
  126. public class RestState : State
  127. {
  128. public override void WriteProgram(Work w)
  129. {
  130. Console.WriteLine("当前时间:{0}点 下班回家了", w.Hour);
  131. }
  132. }
  133.  
  134. //工作
  135. public class Work
  136. {
  137. private State current;
  138. public Work()
  139. {
  140. current = new ForenoonState();
  141. }
  142.  
  143. private double hour;
  144. public double Hour
  145. {
  146. get { return hour; }
  147. set { hour = value; }
  148. }
  149.  
  150. private bool finish = false;
  151. public bool TaskFinished
  152. {
  153. get { return finish; }
  154. set { finish = value; }
  155. }
  156.  
  157. public void SetState(State s)
  158. {
  159. current = s;
  160. }
  161.  
  162. public void WriteProgram()
  163. {
  164. current.WriteProgram(this);
  165. }
  166. }
  167. }

状态者模式的应用场景

在以下情况下可以考虑使用状态者模式。

  • 当一个对象状态转换的条件表达式过于复杂时可以使用状态者模式。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
  • 当一个对象行为取决于它的状态,并且它需要在运行时刻根据状态改变它的行为时,就可以考虑使用状态者模式。

javascript版本的状态机:

  1. var Light = function(){
  2. this.currState = FSM.off; //设置当前状态
  3. this.button = null;
  4. };
  5.  
  6. Light.prototype.init = function(){
  7. var button = document.createElement('button'),
  8. self = this;
  9.  
  10. button.innerHTML = '已关灯';
  11. this.button = document.body.appendChild(button);
  12.  
  13. this.button.onclick = function(){
  14. self.currState.buttonWasPressed.call(self); //把请求委托给FSM状态机
  15. }
  16. };
  17.  
  18. var FSM = {
  19. off:{
  20. buttonWasPressed:function(){
  21. console.log('关灯');
  22. this.button.innerHTML = '下一次按我是开灯';
  23. this.currState = FSM.on;
  24. }
  25. },
  26. on:{
  27. buttonWasPressed:function(){
  28. console.log('开灯');
  29. this.button.innerHTML = '下一次按我是关灯';
  30. this.currState = FSM.off;
  31. }
  32. }
  33. };
  34.  
  35. var light = new Light();
  36. light.init();

实际项目中的其他状态机:

  1. var FSM = {
  2. walk:{
  3. attack:function(){
  4. console.log('攻击');
  5. },
  6. defense:function(){
  7. console.log('防御');
  8. },
  9. jump:function(){
  10. console.log('跳跃');
  11. }
  12. },
  13.  
  14. attack:{
  15. walk:function(){
  16. console.log('攻击的时候不能行走');
  17. },
  18. defense:function(){
  19. console.log('攻击的时候不能防御');
  20. },
  21. jump:function(){
  22. console.log('攻击的时候不能跳跃');
  23. }
  24. }
  25. };

状态模式的电灯程序:

  1. var Light = function(){
  2. this.currState = FSM.off; //设置当前状态
  3. };
  4.  
  5. Light.prototype.init = function(){
  6. self = this;
  7.  
  8. this.button.onclick = function(){
  9. self.currState.buttonWasPressed.call(self); //把请求委托给FSM状态机
  10. }
  11. };
  12.  
  13. var FSM = {
  14. off:{
  15. buttonWasPressed:function(){
  16. console.log('弱光');
  17. this.currState = FSM.weak;
  18. }
  19. },
  20. weak:{
  21. buttonWasPressed:function(){
  22. console.log('强光');
  23. this.currState = FSM.strong;
  24. }
  25. },
  26. strong:{
  27. buttonWasPressed:function(){
  28. console.log('关灯');
  29. this.currState = FSM.off;
  30. }
  31. }
  32. };
  33.  
  34. var light = new Light();
  35. light.init();

状态模式-水的三态变化

用js模拟物理现象,实现水的三态变化,初中物理课我们都学过,物质具有三态变化,气态 -> 液态 -> 固态 或者 固态 -> 液态 -> 气态,但是不可以气态 -> 固态,或者固态 -> 气态,是需要经过液态过度的,否则就违反了自然规律。所以这种状态的变化非常适合用状态模式来实现。代码如下:

  1. var Water = function(){
  2. this.currState = FSM.gas; //设置当前状态
  3. this.h3 = null;
  4. };
  5.  
  6. Water.prototype.init = function(){
  7. var button1 = document.createElement('button'),
  8. button2 = document.createElement('button'),
  9. button3 = document.createElement('button'),
  10. h3 = document.createElement('h3'),
  11. self = this;
  12.  
  13. button1.innerHTML = '100度以上';
  14. button1.onclick = function(){
  15. self.currState.gas.call(self);
  16. }
  17.  
  18. button2.innerHTML = '0-100度';
  19. button2.onclick = function(){
  20. self.currState.liquid.call(self);
  21. }
  22.  
  23. button3.innerHTML = '0度以下';
  24. button3.onclick = function(){
  25. self.currState.solid.call(self);
  26. }
  27.  
  28. document.body.appendChild(button1);
  29. document.body.appendChild(button2);
  30. document.body.appendChild(button3);
  31. this.h3 = document.body.appendChild(h3);
  32. };
  33.  
  34. var FSM = {
  35. gas:{ //气态
  36. liquid:function(){
  37. console.log('液态');
  38. this.h3.innerHTML = '液态';
  39. this.currState = FSM.liquid;
  40. },
  41. solid:function(){
  42. console.log('气态不能变化为固态');
  43. alert('气态不能变化为固态');
  44. }
  45. },
  46. liquid:{ //液态
  47. solid:function(){
  48. console.log('固态');
  49. this.h3.innerHTML = '固态';
  50. this.currState = FSM.solid;
  51. },
  52. gas:function(){
  53. console.log('气态');
  54. this.h3.innerHTML = '气态';
  55. this.currState = FSM.gas;
  56. }
  57. },
  58. solid:{ //固态
  59. gas:function(){
  60. console.log('固态不能变化为气态');
  61. alert('固态不能变化为气态');
  62. },
  63. liquid:function(){
  64. console.log('液态');
  65. this.h3.innerHTML = '液态';
  66. this.currState = FSM.liquid;
  67. }
  68. }
  69. };
  70. var water = new Water();
  71. water.init();

js状态模式的更多相关文章

  1. JS常用的设计模式(17)—— 状态模式

    状态模式主要可以用于这种场景 1 一个对象的行为取决于它的状态 2 一个操作中含有庞大的条件分支语句 回想下街头霸王的游戏. 隆有走动,攻击,防御,跌倒,跳跃等等多种状态,而这些状态之间既有联系又互相 ...

  2. js策略模式vs状态模式

    一.策略模式 1.定义:把一些小的算法,封装起来,使他们之间可以相互替换(把代码的实现和使用分离开来)2.利用策略模式实现小方块缓动 html代码: <div id="containe ...

  3. js设计模式——5.状态模式

    js设计模式——5.状态模式 代码演示 /*js设计模式——状态模式*/ // 状态(红灯,黄灯,绿灯) class State { constructor(color) { this.color = ...

  4. 8.js模式-状态模式

    1. 状态模式 var offLightState = function(light){ this.light = light; } offLightState.prototype.buttonWas ...

  5. 大熊君说说JS与设计模式之------状态模式State

    一,总体概要 1,笔者浅谈 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式. 状态模式主要解决的是当控制一个对象状态的条件表达式过于 ...

  6. JS设计模式(13)状态模式

    什么是状态模式? 定义:将事物内部的每个状态分别封装成类,内部状态改变会产生不同行为. 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为. 何时使用:代码中包含大 ...

  7. js 设计模式——状态模式

    状态模式 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 简单的解释一下: 第一部分的意思是将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态改变时,会带来 ...

  8. js之状态模式

    level01:电灯程序 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  9. Javascript设计模式理论与实战:状态模式

    在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将其抽象出来称为状态,我们平时开发时本质上就是对应用程序的各种状态进行切换并作出相应处理.状态模式就是一种适合多种状态场景下的设计模式 ...

随机推荐

  1. 巨蟒django之CRM3 添加和编辑客户&&公户和私户的展示和转换

    昨日内容回顾: day66 1. 内容回顾 1. 数据的展示 数据通过ORM查询出来 对象列表 QuerySet 1. 普通的字段 对象.字段名 ——> 数据库中的值 2. choices (( ...

  2. Springboot 1.5.x版本上读取自定义配置文件问题

    原来的解决方案: 现在1.5.x以后取消了location地址 1.5以后解决方案:

  3. Linux下简单的多线程编程--线程池的实现

    /* 写在前面的话: 今天刚“开原”,选择了一篇关于线程池的文件与大家分享,希望能对您学习有所帮助,也希望能与大家共同学习! 选择在这个特殊的时候注册并发文章也是有一些我个人特殊的意义的,看我的id( ...

  4. Java关键字this

    Java关键字this只能用于方法方法体内.当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this.因此,this只能在类中的非静态方法中使用,静 ...

  5. msql 2000 使用DBCC CHECK DB 得出错误,槽引用错误

    转自:http://www.cnblogs.com/firstrose/p/4256257.html 某个SQL2000的数据库,在通过备份/还原的方法升级到2005时发生错误: 查找解决方法未果 正 ...

  6. Spring学习笔记3—声明式事务

    1 理解事务 事务:在软件开发领域,全有或全无的操作被称为事务.事务允许我们将几个操作组合成一个要么全部发生要么全部不发生的工作单元. 事务的特性: 原子性:事务是由一个或多个活动所组成的一个工作单元 ...

  7. windows中使用Findwindow函数与FindWindowEx函数来实现自动控制、触发第三方软件事件的方法

    FindWindow 用来根据类名和窗口名来得到窗口句柄的.但是这个函数不能查找子窗口,也不区分大小写. 如果要从一个窗口的子窗口中查找需要使用FindWindowEX. 如果要搜索的外部程序的窗口标 ...

  8. 分布式计算开源框架Hadoop入门实践(三)

    Hadoop基本流程 一个图片太大了,只好分割成为两部分.根据流程图来说一下具体一个任务执行的情况. 在分布式环境中客户端创建任务并提交. InputFormat做Map前的预处理,主要负责以下工作: ...

  9. 系统非正常关机启动后出现:an error occurred during the file system

    现象描述: 1.系统ssh登录报Too many open files in system,系统登录不进去,就直接强制关机了,开机后出现(2)的错误: 由于文件描述符用完了,需要把fs.file-ma ...

  10. 对”唯一键可以包含NULL值,并且每个NULL值都是唯一的(即NULL!=NULL)“理解

    因为最近在写一篇关于字符串模糊检索的论文,开始比较细致的研究数据库(MySQL)中的index问题,变到图书馆借了本<Effective MySQL之SQL语句最优化>(Ronald Br ...