目的

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。

类图

状态类图.png

实现

糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。
状态1.jpg

  1. public interface State {
  2. /**
  3. * 投入 25 分钱
  4. */
  5. void insertQuarter();
  6. /**
  7. * 退回 25 分钱
  8. */
  9. void ejectQuarter();
  10. /**
  11. * 转动曲柄
  12. */
  13. void turnCrank();
  14. /**
  15. * 发放糖果
  16. */
  17. void dispense();
  18. }
  19. public class HasQuarterState implements State {
  20. private GumballMachine gumballMachine;
  21. public HasQuarterState(GumballMachine gumballMachine) {
  22. this.gumballMachine = gumballMachine;
  23. }
  24. @Override
  25. public void insertQuarter() {
  26. System.out.println("You can't insert another quarter");
  27. }
  28. @Override
  29. public void ejectQuarter() {
  30. System.out.println("Quarter returned");
  31. gumballMachine.setState(gumballMachine.getNoQuarterState());
  32. }
  33. @Override
  34. public void turnCrank() {
  35. System.out.println("You turned...");
  36. gumballMachine.setState(gumballMachine.getSoldState());
  37. }
  38. @Override
  39. public void dispense() {
  40. System.out.println("No gumball dispensed");
  41. }
  42. }
  43. public class NoQuarterState implements State {
  44. GumballMachine gumballMachine;
  45. public NoQuarterState(GumballMachine gumballMachine) {
  46. this.gumballMachine = gumballMachine;
  47. }
  48. @Override
  49. public void insertQuarter() {
  50. System.out.println("You insert a quarter");
  51. gumballMachine.setState(gumballMachine.getHasQuarterState());
  52. }
  53. @Override
  54. public void ejectQuarter() {
  55. System.out.println("You haven't insert a quarter");
  56. }
  57. @Override
  58. public void turnCrank() {
  59. System.out.println("You turned, but there's no quarter");
  60. }
  61. @Override
  62. public void dispense() {
  63. System.out.println("You need to pay first");
  64. }
  65. }
  66. public class SoldOutState implements State {
  67. GumballMachine gumballMachine;
  68. public SoldOutState(GumballMachine gumballMachine) {
  69. this.gumballMachine = gumballMachine;
  70. }
  71. @Override
  72. public void insertQuarter() {
  73. System.out.println("You can't insert a quarter, the machine is sold out");
  74. }
  75. @Override
  76. public void ejectQuarter() {
  77. System.out.println("You can't eject, you haven't inserted a quarter yet");
  78. }
  79. @Override
  80. public void turnCrank() {
  81. System.out.println("You turned, but there are no gumballs");
  82. }
  83. @Override
  84. public void dispense() {
  85. System.out.println("No gumball dispensed");
  86. }
  87. }
  88. public class SoldState implements State {
  89. GumballMachine gumballMachine;
  90. public SoldState(GumballMachine gumballMachine) {
  91. this.gumballMachine = gumballMachine;
  92. }
  93. @Override
  94. public void insertQuarter() {
  95. System.out.println("Please wait, we're already giving you a gumball");
  96. }
  97. @Override
  98. public void ejectQuarter() {
  99. System.out.println("Sorry, you already turned the crank");
  100. }
  101. @Override
  102. public void turnCrank() {
  103. System.out.println("Turning twice doesn't get you another gumball!");
  104. }
  105. @Override
  106. public void dispense() {
  107. gumballMachine.releaseBall();
  108. if (gumballMachine.getCount() > 0) {
  109. gumballMachine.setState(gumballMachine.getNoQuarterState());
  110. } else {
  111. System.out.println("Oops, out of gumballs");
  112. gumballMachine.setState(gumballMachine.getSoldOutState());
  113. }
  114. }
  115. }
  116. public class GumballMachine {
  117. private State soldOutState;
  118. private State noQuarterState;
  119. private State hasQuarterState;
  120. private State soldState;
  121. private State state;
  122. private int count = 0;
  123. public GumballMachine(int numberGumballs) {
  124. count = numberGumballs;
  125. soldOutState = new SoldOutState(this);
  126. noQuarterState = new NoQuarterState(this);
  127. hasQuarterState = new HasQuarterState(this);
  128. soldState = new SoldState(this);
  129. if (numberGumballs > 0) {
  130. state = noQuarterState;
  131. } else {
  132. state = soldOutState;
  133. }
  134. }
  135. public void insertQuarter() {
  136. state.insertQuarter();
  137. }
  138. public void ejectQuarter() {
  139. state.ejectQuarter();
  140. }
  141. public void turnCrank() {
  142. state.turnCrank();
  143. state.dispense();
  144. }
  145. public void setState(State state) {
  146. this.state = state;
  147. }
  148. public void releaseBall() {
  149. System.out.println("A gumball comes rolling out the slot...");
  150. if (count != 0) {
  151. count -= 1;
  152. }
  153. }
  154. public State getSoldOutState() {
  155. return soldOutState;
  156. }
  157. public State getNoQuarterState() {
  158. return noQuarterState;
  159. }
  160. public State getHasQuarterState() {
  161. return hasQuarterState;
  162. }
  163. public State getSoldState() {
  164. return soldState;
  165. }
  166. public int getCount() {
  167. return count;
  168. }
  169. }
  170. public class Client {
  171. public static void main(String[] args) {
  172. GumballMachine gumballMachine = new GumballMachine(5);
  173. gumballMachine.insertQuarter();
  174. gumballMachine.turnCrank();
  175. gumballMachine.insertQuarter();
  176. gumballMachine.ejectQuarter();
  177. gumballMachine.turnCrank();
  178. gumballMachine.insertQuarter();
  179. gumballMachine.turnCrank();
  180. gumballMachine.insertQuarter();
  181. gumballMachine.turnCrank();
  182. gumballMachine.ejectQuarter();
  183. gumballMachine.insertQuarter();
  184. gumballMachine.insertQuarter();
  185. gumballMachine.turnCrank();
  186. gumballMachine.insertQuarter();
  187. gumballMachine.turnCrank();
  188. gumballMachine.insertQuarter();
  189. gumballMachine.turnCrank();
  190. }
  191. }
  192. 运行结果
  193. You insert a quarter
  194. You turned...
  195. A gumball comes rolling out the slot...
  196. You insert a quarter
  197. Quarter returned
  198. You turned, but there's no quarter
  199. You need to pay first
  200. You insert a quarter
  201. You turned...
  202. A gumball comes rolling out the slot...
  203. You insert a quarter
  204. You turned...
  205. A gumball comes rolling out the slot...
  206. You haven't insert a quarter
  207. You insert a quarter
  208. You can't insert another quarter
  209. You turned...
  210. A gumball comes rolling out the slot...
  211. You insert a quarter
  212. You turned...
  213. A gumball comes rolling out the slot...
  214. Oops, out of gumballs
  215. You can't insert a quarter, the machine is sold out
  216. You turned, but there are no gumballs
  217. No gumball dispensed