第十六章 状态模式(无尽加班何时休)

  1. //工作状态
  2. abstract class State
  3. {
  4. abstract public function WriteProgram(Work $w);
  5. }
  6. class ForenoonState extends State
  7. {
  8. public function WriteProgram(Work $w)
  9. {
  10. if ($w->getHour() < 12) {
  11. echo "当前时间:".$w->getHour()." 上午工作,精神百倍\n";
  12. } else {
  13. $w->setState(new NoonState());
  14. $w->WriteProgram();
  15. }
  16. }
  17. }
  18. class NoonState extends State
  19. {
  20. public function WriteProgram(Work $w)
  21. {
  22. if ($w->getHour() < 13) {
  23. echo "当前时间:".$w->getHour()." 饿了,午饭;犯困,午休\n";
  24. } else {
  25. $w->setState(new AfterNoonState());
  26. $w->WriteProgram();
  27. }
  28. }
  29. }
  30. class AfterNoonState extends State
  31. {
  32. public function WriteProgram(Work $w)
  33. {
  34. if ($w->getHour() < 17) {
  35. echo "当前时间:".$w->getHour()." 下午状态不错,继续努力\n";
  36. } else {
  37. $w->setState(new EveningState());
  38. $w->WriteProgram();
  39. }
  40. }
  41. }
  42. class EveningState extends State
  43. {
  44. public function WriteProgram(Work $w)
  45. {
  46. if ($w->getTaskFinishedState()) {
  47. //如果完成任务,下班
  48. $w->setState(new RestState());
  49. $w->WriteProgram();
  50. } else {
  51. if ($w->getHour() < 21) {
  52. echo "当前时间:".$w->getHour()." 加班哦,疲惫之极\n";
  53. } else {
  54. //超过21点,则转入睡眠工作状态
  55. $w->setState(new SleepingState());
  56. $w->WriteProgram();
  57. }
  58. }
  59. }
  60. }
  61. class SleepingState extends State
  62. {
  63. public function WriteProgram(Work $w)
  64. {
  65. echo "当前时间:".$w->getHour()." 不行了,睡觉\n";
  66. }
  67. }
  68. class RestState extends State
  69. {
  70. public function WriteProgram(Work $w)
  71. {
  72. echo "当前时间:".$w->getHour()." 下班回家\n";
  73. }
  74. }
  75. class Work
  76. {
  77. private $current;
  78. function __construct()
  79. {
  80. $this->current = new ForenoonState();
  81. }
  82. private $hour;
  83. public function getHour()
  84. {
  85. return $this->hour;
  86. }
  87. public function setHour($hour)
  88. {
  89. $this->hour = $hour;
  90. }
  91. private $finished = false;
  92. public function setTaskFinished($bool)
  93. {
  94. $this->finished = $bool;
  95. }
  96. public function getTaskFinishedState()
  97. {
  98. return $this->finished;
  99. }
  100. public function setState(State $state)
  101. {
  102. $this->current = $state;
  103. }
  104. public function WriteProgram()
  105. {
  106. $this->current->WriteProgram($this);
  107. }
  108. }
  109. //客户端代码
  110. $emergencyProjects = new Work();
  111. $emergencyProjects->setHour(9);
  112. $emergencyProjects->WriteProgram();
  113. $emergencyProjects->setHour(10);
  114. $emergencyProjects->WriteProgram();
  115. $emergencyProjects->setHour(12);
  116. $emergencyProjects->WriteProgram();
  117. $emergencyProjects->setHour(13);
  118. $emergencyProjects->WriteProgram();
  119. $emergencyProjects->setHour(14);
  120. $emergencyProjects->WriteProgram();
  121. $emergencyProjects->setHour(17);
  122. $emergencyProjects->setTaskFinished(false);
  123. $emergencyProjects->WriteProgram();
  124. $emergencyProjects->setHour(19);
  125. $emergencyProjects->WriteProgram();
  126. $emergencyProjects->setHour(22);
  127. $emergencyProjects->WriteProgram();

总结:

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

面向对象设计其实就是希望做到代码的责任分解。

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

将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。

将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义的子类可以很容易地增加新的状态和转换。

消除了庞大的条件分支语句。

状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少项目之间的依赖。

当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。