java设计模式之State(状态)
来源:互联网 发布:暴走大事件 恶劣 知乎 编辑:程序博客网 时间:2024/06/05 12:39
状态模式是在程序开发时,经常用到的模式。如果没有应用过,而实现业务功能。那你也一定是按照状态模式的路子走的,只不过你没有感觉到而已。它的实现,是要根据对象的内部状态变化,而自动执行相应的功能。
费话就不说了,请看一下源代码,这也是我研究设计模式时看到的一个例子,把其翻译成中文,使个位网友能够看懂些,由于水平有限,只能达到这样,还希望读者多指证,谢谢啊。
1. public class GumballMachine {
2. //这就是那4个状态,每个状态都用一个不同的整数代表,他们符合状态图
3. final static int SOLD_OUT = 0; //糖果售完状态
4. final static int NO_QUARTER = 1; //没有钱状态
5. final static int HAS_QUARTER = 2; //有钱状态
6. final static int SOLD = 3; //售出糖果
7. //这个实例变量跟踪当前状态,一开始被设为"糖果售完",因为糖果机安装时是没有装糖果的
8. int state = SOLD_OUT;
9. int count = 0; //这个变量用来追踪机器内的糖果数目
10. //构造器初始糖果库存量当做参数,如果库存不为0的话,机器就进入"没有钱"的状态,等着你向里投钱
11. public GumballMachine(int count) {
12. this.count = count;
13. if (count > 0) {
14. state = NO_QUARTER;
15. }
16. }
17.
18. //当把钱投入进来,就会执行这里
19. public void insertQuarter() {
20. if (state == HAS_QUARTER) {
21. //如果此时的状态为有钱状态,则通知顾客
22. System.out.println("你不能再向糖果机里投钱了");
23. } else if (state == NO_QUARTER) {
24. //如果是在"没有25分钱"的状态下,我们就接受25分钱,并将状态转换到"有25分钱"
25. state = HAS_QUARTER;
26. System.out.println("你可以向糖果机里投钱");
27. } else if (state == SOLD_OUT) {
28. //如果糖果售完,就拒绝收钱
29. System.out.println("糖果已经卖完,不能再向里投钱了");
30. } else if (state == SOLD) {
31. //如果顾客买到糖果,就需要稍等下,好让状态转换完毕,恢复到"没有25分钱"的状态
32. System.out.println("已向你卖出一个糖果,请稍等,再向里投钱。");
33. }
34. }
35. //现在,如果顾客试着退回25分钱...
36. public void ejectQuarter() {
37. if (state == HAS_QUARTER) {
38. //如果有25分钱,就退钱,回到"没有25分钱"的状态
39. System.out.println("退钱成功");
40. state = NO_QUARTER;
41. } else if (state == NO_QUARTER) {
42. //如果没有25分钱,当然不能退回
43. System.out.println("没有钱,你不能退钱");
44. } else if (state == SOLD) {
45. //如果顾客已经转动手柄,就不能退钱了,他已经拿到糖果了
46. state = NO_QUARTER;
47. System.out.println("对不起,糖果已经卖出不能退钱。");
48. } else if (state == SOLD_OUT) {
49. //如果糖果售完,就不可能接受25分钱,当然也不可能退钱
50. System.out.println("对不起,糖果已经卖完不能退钱");
51. }
52. }
53. //顾客试着转动手柄...
54. public void turnCrank() {
55. if (state == SOLD) {
56. //别想骗过机器拿2次糖果
57. System.out.println("不能再给你了");
58. } else if (state == NO_QUARTER) {
59. //我们需要先投入25分钱
60. System.out.println("你没有投钱糖果不能卖给你");
61. } else if (state == SOLD_OUT) {
62. //没有糖果了
63. System.out.println("糖果机中没有糖果了,你不能进行交易。");
64. } else if (state == HAS_QUARTER) {
65. //成功!他拿到糖果了.改变状态到"售出糖果",然后调用机器的dispense()方法
66. System.out.println("请稍等,一会糖果你就可以拿到了...");
67. state = SOLD;
68. dispense();
69. }
70. }
71. //发放糖果
72. public void dispense() {
73. if (state == SOLD) {
74. //我们正在"售出糖果"状态
75. System.out.println("一个糖果将从这里出来....");
76. count = count - 1;
77. //我们在这里处理"糖果售完"的情况
78. if (count == 0) { //最后一颗,将机器设置到"糖果售完"状态
79. System.out.println("库存为零!");
80. state = SOLD_OUT;
81. } else { //否则回到"没有25分钱"的状态
82. state = NO_QUARTER;
83. }
84. } else if (state == NO_QUARTER) {
85. //以下都不应该发生,但如果顾客这么做了,得到的应该是错误消息而不是糖果
86. System.out.println("你需要向糖果机里投钱。。");
87. } else if (state == SOLD_OUT) {
88. System.out.println("糖果已经卖没了");
89. } else if (state == HAS_QUARTER) {
90. System.out.println("请您稍等交易还没有结束。");
91. }
92. }
93. }
测试就来自已写吧,我提供个思路,就是页面提供几个开关,即按纽、checkbox等在它们的单击事件上GumballMachine实例的内部状态改变。然后看其变化,就可以了。
大家看没看出来,这段代码还有一些“怪的味道”呀,这时如果业务变化了,如果客户是一个中奖的用户,需要糖果机吐出两块糖果,怎么办?,是不是还得在各个方法中把这个状态给加上呀,又得加一个if语句呢,这是一个业务发生了变化,如果业务要无限的变化下去,程序员是不是都要疯了,哈哈。所以要对其进行重构了。
要把这几个状态抽象出来。想到这里看一下代码就明白了。
Java代码
1. public interface State {
2. //投钱的状态
3. public void insertQuarter();
4. //退钱的状态
5. public void ejectQuarter();
6. //按下按纽状态
7. public void turnCrank();
8. //发放物品状态
9. public void dispense();
10. }
下面是几个实现这个状态接口的实现类。
Java代码
1. public class HasQuarterState implements State {
2. GumballMachineTwo gumballMachine;
3. //增加一个随机数产生器,产生10%的机会
4. Random randomWinner = new Random(System.currentTimeMillis());
5. public HasQuarterState(GumballMachineTwo gumballMachine) {
6. this.gumballMachine = gumballMachine;
7. }
8. public void insertQuarter() { //这是一个对当前状态不恰当的动作
9. System.out.println("不能再投钱了,已经有钱了。");
10. }
11.
12. public void ejectQuarter() { //退钱并转换状态到NoQuarterState
13. System.out.println("退钱返回");
14. //把糖果机从有钱状态改成没钱状态
15. gumballMachine.setState(gumballMachine.getNoQuarterState());
16. }
17.
18. public void turnCrank() {
19. System.out.println("请稍等,一会糖果你就可以拿到了...");
20. int winner = randomWinner.nextInt(10);
21. //决定这个顾客是否赢了
22. if ((winner == 0) && (gumballMachine.getCount() > 1)) {
23. gumballMachine.setState(gumballMachine.getWinnerState());
24. } else {
25. gumballMachine.setState(gumballMachine.getSoldState());
26. }
27. }
28. public void dispense() { //这是一个对当前状态不恰当的动作
29. System.out.println("请您稍等交易还没有结束。");
30. }
31. }
32.
33. public class NoQuarterState implements State {
34. GumballMachineTwo gumballMachine;
35.
36. // 通过构造器得到糖果机的引用
37. public NoQuarterState(GumballMachineTwo gumballMachine) {
38. this.gumballMachine = gumballMachine;
39. }
40.
41. // 分发物品
42. public void dispense() {
43. System.out.println("没有钱,不能分发糖果");
44. }
45.
46. // 退钱
47. public void ejectQuarter() {
48. System.out.println("没有钱,不能退钱");
49. }
50.
51. // 投钱
52. public void insertQuarter() {
53. // TODO Auto-generated method stub
54. }
55.
56. // 按纽操作
57. public void turnCrank() {
58. // TODO Auto-generated method stub
59. }
60. }
61.
62. public class SoldOutState implements State {
63. GumballMachineTwo gumballMachine;
64.
65. public SoldOutState(GumballMachineTwo gumballMachine) {
66. this.gumballMachine = gumballMachine;
67. }
68.
69. public void dispense() {
70. System.out.println("糖果已经卖没了");
71. }
72.
73. public void ejectQuarter() {
74. System.out.println("对不起,糖果已经卖完不能退钱");
75.
76. }
77.
78. public void insertQuarter() {
79. System.out.println("糖果已经卖完,不能再向里投钱了");
80. }
81.
82. public void turnCrank() {
83. // TODO Auto-generated method stub
84. }
85. }
86.
87. public class SoldState implements State {
88. GumballMachineTwo gumballMachine;
89. public SoldState(GumballMachineTwo gumballMachine) {
90. this.gumballMachine = gumballMachine;
91. }
92. //以下3个方法对此状态来说都是不恰当的
93. public void insertQuarter() {
94. System.out.println("已向你卖出一个糖果,请稍等,再向里投钱。");
95. }
96. public void ejectQuarter() {
97. System.out.println("对不起,糖果已经卖出不能退钱");
98. }
99. public void turnCrank() {
100. System.out.println("糖果已经卖出,不能再给你了");
101. }
102. //首先让机器发放糖果
103. public void dispense() {
104. gumballMachine.releaseBall();
105. if (gumballMachine.getCount() > 0) {
106. gumballMachine.setState(gumballMachine.getNoQuarterState());
107. } else {
108. System.out.println("Oops, out of gumballs!");
109. gumballMachine.setState(gumballMachine.getSoldOutState());
110. }
111. }
112.}
113.
114. public class WinnerState implements State {
115. GumballMachineTwo gumballMachine;
116. //下面都跟SoldState方法一样
117. public WinnerState(GumballMachineTwo gumballMachine) {
118. this.gumballMachine = gumballMachine;
119. }
120. public void insertQuarter() {
121. System.out.println("Please wait, we're already giving you a Gumball");
122. }
123. public void ejectQuarter() {
124. System.out.println("Please wait, we're already giving you a Gumball");
125. }
126. public void turnCrank() {
127. System.out.println("Turning again doesn't get you another gumball!");
128. }
129. //我们在这里发放出2颗糖果,然后进入NoQuarterState或SoldState
130. public void dispense() {
131. System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter");
132. gumballMachine.releaseBall();
133. if (gumballMachine.getCount() == 0) {
134. gumballMachine.setState(gumballMachine.getSoldOutState());
135. } else {
136. gumballMachine.releaseBall();
137. if (gumballMachine.getCount() > 0) {
138. gumballMachine.setState(gumballMachine.getNoQuarterState());
139. } else {
140. System.out.println("Oops, out of gumballs!");
141. gumballMachine.setState(gumballMachine.getSoldOutState());
142. }
143. }
144. }
145.}
下面是新的糖果类:
Java代码
1. public class GumballMachineTwo {
2. //所有的状态都在这里
3. State soldOutState;
4. State noQuarterState;
5. State hasQuarterState;
6. State soldState;
7.
8. State winnerState;//十次抽中一次的游戏,新的状态
9. //以及实例变量state
10. State state = soldOutState;
11. int count = 0;//记录糖果数量
12. public GumballMachineTwo(int numberGumballs) {
13. soldOutState = new SoldOutState(this); //每一种状态也都创建一个状态实例
14. noQuarterState = new NoQuarterState(this);
15. hasQuarterState = new HasQuarterState(this);
16. soldState = new SoldState(this);
17. this.count = numberGumballs;
18. if (numberGumballs > 0) { //如果超过0颗糖果,状态设为noQuarterState
19. state = noQuarterState;
20. }
21. }
22. //委托给当前状态
23. public void insertQuarter() {
24. state.insertQuarter();
25. }
26. public void ejectQuarter() {
27. state.ejectQuarter();
28. }
29. //dispense()是一个内部动作方法,用户不可以直接要求机器发放糖果
30. public void turnCrank() {
31. state.turnCrank();
32. state.dispense();
33. }
34. //允许其他的对象将机器状态转换到不同的状态
35. void setState(State state) {
36. this.state = state;
37. }
38. //辅助方法释放出糖果,并将count实例变量值减1
39. void releaseBall() {
40. System.out.println("A gumball comes rolling out the slot...");
41. if (count != 0) {
42. count = count - 1;
43. }
44. }
45. int getCount() {
46. return count;
47. }
48. void refill(int count) {
49. this.count = count;
50. state = noQuarterState;
51. }
52. public State getState() {return state;}
53. public State getSoldOutState() {return soldOutState;}
54. public State getNoQuarterState() {return noQuarterState;}
55. public State getHasQuarterState() {return hasQuarterState;}
56. public State getSoldState() {return soldState;}
57. public State getWinnerState() {return winnerState;}
58. }
- Java设计模式之State(状态模式)
- java设计模式之状态 模式State
- java设计模式之State(状态)
- 设计模式之State(状态)
- Java 设计模式 之 状态模式(State)
- JAVA设计模式之 状态模式【State Pattern】
- Java设计模式之--状态模式(State)
- Java 设计模式 之 状态模式(State)
- Java 设计模式 之 状态模式(State)
- Java 设计模式 之 状态模式(State)
- JAVA设计模式九之状态模式State
- Java语言设计模式之状态模式(State)
- 设计模式之状态设计模式,state
- 设计模式之state状态模式
- 设计模式之State Pattern 状态模式。
- 设计模式之State(状态模式)
- 设计模式之(十七)状态模式State
- 设计模式之状态模式(State Pattern)
- #ifdef的用法
- 热烈祝贺逐浪CMS1.0发布
- java设计模式之Command(命令)
- js用FileSystemObject 对象实现文件控制
- [矿工]电信重组大格局,中国联通的攻守之道
- java设计模式之State(状态)
- DataGridView控件用法合集(九-十一)
- dataGridview中的分页功能实现(多个对像,不是单一的)
- .NET Framework 3.5 安装失败
- 双体,我能否与你相遇?!
- Oracle 游标使用大全(二)
- Shared objects compared with cookies
- 从硬盘安装openSuSE linux 11
- native2ascii