状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了他的类。

用到的设计原则
1、封装变化
2、多用组合,少用继承
3、针对接口编程,不针对实现编程
4、松耦合
5、对扩展开放,对修改关闭
6、依赖抽象,而不依赖具体
7、只和朋友交谈
8、别找我,我会找你
9、类应该只有一个修改的理由

例子来自《Head First设计模式》,糖果机的例子

  1. interface State {
  2.  
  3. public void insertQuarter();
  4.  
  5. public void ejectQuarter();
  6.  
  7. public void turnCrank();
  8.  
  9. public void dispense();
  10. }
  11.  
  12. class NoQuarterState implements State {
  13. GumballMachine gumballMachine;
  14.  
  15. public NoQuarterState(GumballMachine gumballMachine) {
  16. this.gumballMachine = gumballMachine;
  17. }
  18.  
  19. public void insertQuarter() {
  20. System.out.println("You inserted a quarter");
  21. gumballMachine.setState(gumballMachine.hasQuarterState);
  22. }
  23.  
  24. public void ejectQuarter() {
  25. System.out.println("You haven't inserted a quarter");
  26. }
  27.  
  28. public void turnCrank() {
  29. System.out.println("You turned, but there's no quarter");
  30. }
  31.  
  32. public void dispense() {
  33. System.out.println("You need to pay first");
  34. }
  35.  
  36. public String toString() {
  37. return "waiting for quarter";
  38. }
  39. }
  40.  
  41. class HasQuarterState implements State {
  42. Random randomWinner = new Random(System.currentTimeMillis());
  43. GumballMachine gumballMachine;
  44.  
  45. public HasQuarterState(GumballMachine gumballMachine) {
  46. this.gumballMachine = gumballMachine;
  47. }
  48.  
  49. public void insertQuarter() {
  50. System.out.println("You can't insert another quarter");
  51. }
  52.  
  53. public void ejectQuarter() {
  54. System.out.println("Quarter returned");
  55. gumballMachine.setState(gumballMachine.noQuarterState);
  56. }
  57.  
  58. public void turnCrank() {
  59. System.out.println("You turned...");
  60.  
  61. int winner = randomWinner.nextInt(10);
  62. if ((winner == 0) && (gumballMachine.count > 1)) {
  63. gumballMachine.setState(gumballMachine.winnerState);
  64. } else {
  65. gumballMachine.setState(gumballMachine.soldOutState);
  66. }
  67. }
  68.  
  69. public void dispense() {
  70. System.out.println("No gumball dispensed");
  71. }
  72.  
  73. public String toString() {
  74. return "waiting for turn of crank";
  75. }
  76. }
  77.  
  78. class GumballMachine {
  79. State soldOutState;
  80. State noQuarterState;
  81. State hasQuarterState;
  82. State soldState;
  83. State winnerState;
  84.  
  85. State state = soldOutState;
  86. int count = 0;
  87.  
  88. public GumballMachine(int numberGumballs) {// soldOutState = new SoldOutState(this);
  89. noQuarterState = new NoQuarterState(this);
  90. hasQuarterState = new HasQuarterState(this);
  91. // soldState = new SoldState(this);
  92. // winnerState = new WinnerState(this);
  93.  
  94. this.count = numberGumballs;
  95. if (numberGumballs > 0) {
  96. state = noQuarterState;
  97. }
  98. }
  99.  
  100. public void insertQuarter() {
  101. state.insertQuarter();
  102. }
  103.  
  104. public void ejectQuarter() {
  105. state.ejectQuarter();
  106. }
  107.  
  108. public void turnCrank() {
  109. state.turnCrank();
  110. state.dispense();
  111. }
  112.  
  113. void setState(State state) {
  114. this.state = state;
  115. }
  116.  
  117. void releaseBall() {
  118. System.out.println("A gumball comes rolling out the slot...");
  119. if (count != 0) {
  120. count = count - 1;
  121. }
  122. }
  123.  
  124. }
  125.  
  126. public class StateTest {
  127. public static void main(String[] args) {
  128. GumballMachine gumballMachine = new GumballMachine(10);
  129.  
  130. gumballMachine.insertQuarter();
  131. gumballMachine.turnCrank();
  132. gumballMachine.insertQuarter();
  133. gumballMachine.turnCrank();
  134. }
  135. }

类图:

上面的代码运行不了。缺少三种State,这里只是看一下要表达的意思。

装填模式将状态封装成独立的类,并将每个动作委托给当前状态的对象。如果对象能够完全改变它的行为,那么你会觉得,这个对象实际是从别的类实例化出来的,而实际上,我们是用组合通过简单引用不同的状态对象来造成类的改变的假象。

当我们看到上面的类图时,会发现这个类图和策略模式的类图是一样的。
策略模式:我们将一群行为封装在状态对象中,context的行为随时可委托到哪个状态对象中。随着状态的改变,以反应context的内部的状态。但是context的客户对于状态对象了解不多。状态模式代替多条件判断的设计方案,通过包装状态对象,在context内简单地改变状态对象。
装填模式:通常是主动指定context所要组合的对象是哪一个。这个对象一般情况不会改变,因为对于程序而言,他就是这个类型的,具有特定的行为。一般来说,策略模式是除了继承外一种弹性的设计方案。

状态模式:封装基于装填的行为,并将行为委托到当前状态
策略模式:将可以减缓的行为封装起来,然后使用委托的方法决定使用那一个行为
模板方法模式:由子类决定如何实现算法中的某个步骤

Head First 设计模式 --10 状态模式的更多相关文章

  1. 【转】设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  2. 设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  3. 北风设计模式课程---状态模式State(对象行为型)

    北风设计模式课程---状态模式State(对象行为型) 一.总结 一句话总结: 状态模式 具体状态的行为在具体的状态类中就解决,不用交给外部做判断.实质是将多条件判断弄成了多个类,在不同的类中做判断 ...

  4. python设计模式之状态模式

    python设计模式之状态模式 面向对象编程着力于在对象交互时改变它们的状态.在很多问题中,有限状态机(通常名为状态机)是一个非常方便的状态转换建模(并在必要时以数学方式形式化)工具.首先,什么是状态 ...

  5. 乐在其中设计模式(C#) - 状态模式(State Pattern)

    原文:乐在其中设计模式(C#) - 状态模式(State Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 状态模式(State Pattern) 作者:webabcd 介绍 允 ...

  6. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

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

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

  8. 设计模式2——状态模式State

    参考链接: 设计模式之状态模式:https://www.cnblogs.com/haoerlv/p/7777789.html 设计模式系列之状态模式:https://www.jianshu.com/p ...

  9. 【HeadFirst设计模式】10.状态模式

    定义: 允许对象在内部状态改变时改变它 行为,对象看起来好像修改了它的类. OO原则: 封装变化 多用组合,少用继承 针对接口编程,不针对实现编程 为交互对象之间的松耦合设计而努力 类应该对扩展开放, ...

随机推荐

  1. Select For update语句浅析 (转)

    Select … for update语句是我们经常使用手工加锁语句.通常情况下,select语句是不会对数据加锁,妨碍影响其他的DML和DDL操作.同时,在多版本一致读机制的支持下,select语句 ...

  2. 夺命雷公狗-----React---20--实现验证码大写

    <!DOCTYPE> <html> <head> <meta charset="utf-8"> <title></ ...

  3. QuickRun-快速运行助手

    大家平时需要打开软件的时候都是怎么操作的?一般来说有三种方式: 切换到桌面再点击软件的快捷方式(会将当前正在操作的软件隐藏,再切换回之前的状态比较麻烦,特别是桌面被密密麻麻的图标铺满的时候,找到一个快 ...

  4. Mvc4中使用Spring.Net实现IOC和DI

    一个Hello类,一个IHello接口 1.引用dll 2.修改Global文件 (SpringMvcApplication) 3.控制器添加属性 4.WebConfig配置 5.Spring.xml ...

  5. Java中Map的三种遍历方法

    Map的三种遍历方法: 1. 使用keySet遍历,while循环: 2. 使用entrySet遍历,while循环: 3. 使用for循环遍历.   告诉您们一个小秘密: (下↓面是测试代码,最爱看 ...

  6. windows下使用火狐浏览器插件AutoProxy+MyEnTunnel+SSH访问海外站点(转)

    windows下使用火狐浏览器插件AutoProxy+MyEnTunnel+SSH访问海外站点   平时需要查阅一些技术资料,光走VPN太浪费流量,所以这儿教大家一种使用火狐浏览器的插件 AutoPr ...

  7. ImageView cannot be resolved to a type

    问题: ImageView cannot be resolved to a type 报这样的错误是没有加载MainActivity.java文件中加入 import android.widget.I ...

  8. PHP文件操作:遍历文件目录

    <?php /*遍历目录,列出目录中的文件 * array scandir(string $directory [,int $sorting_order]) * $directory为待遍历目录 ...

  9. BigDecimal使用中的坑

    1.BigeDecimal调用divide时一定要记得规定小数位数的保留情况,不然除不尽的时候报错. 2.使用该种BigeDecimal时,加减乘除都要使用它内部封装好的方法,不然容易报错.

  10. AC6102开发板USB3.0测试和使用说明

    AC6102开发板USB3.0测试和使用说明 概述 AC6102上集成了一颗Cypress 推出的高性能USB3.0传输芯片CYUSB3014,Cypress称之为EZ-USBFX3.该芯片性能强劲, ...