码迷,mamicode.com
首页 > 其他好文 > 详细

headFirst学习笔记之十:状态模式(5.2)

时间:2015-05-02 06:17:24      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:

1.如何从状态图得到真正的代码:

(1)找出所有状态:没有25分钱,有25分钱,糖果售罄,售出糖果。

(2)创建一个实例变量来持有目前状态,并且定义每个状态的值:

1 final static int SOLD_OUT = 0;
2 final static int NO_QUARTER = 1;
3 final static int HAS_QUARTER = 2;
4 final static int SOLD = 3;
5 
6 int state = SOLD_OUT;

(3)找出所有的动作:投入25分钱,退回25分钱,转动曲柄,发放糖果。每一个动作都对应一个方法,而方法内通过条件判断是否可以执行这个动作。

(4)创建一个类,模拟状态机。

 1 public class GumballMachine {
 2     final static int SOLD_OUT = 0;//售罄
 3     final static int NO_QUARTER = 1;//无25分
 4     final static int HAS_QUARTER = 2;//有25分
 5     final static int SOLD = 3;//售出糖果
 6      
 7     int state = SOLD_OUT;
 8     int count = 0;//糖果机内糖果数量
 9     
10     public GumballMachine(int count) {
11         super();
12         this.count = count;
13         //如果库存不为0,就会进入“没有25分”,来等待别人投钱。否则就进入“售罄”,无法投钱
14         if(count>0){
15             state = NO_QUARTER;
16         }
17     }
18     //投钱
19     public void insertQuater(){
20         if(state == HAS_QUARTER){
21             System.out.println("已经投过25分");
22         }
23         else if(state == NO_QUARTER){
24             System.out.println("你投入了25分");
25             state = HAS_QUARTER;
26         }
27         else if(state == SOLD_OUT){
28             System.out.println("已经售罄,无法投钱");
29         }
30         else if(state == SOLD){
31             System.out.println("正在出糖果,请等待一会再投钱");
32         }
33     }
34     //退钱
35     public void ejectQuater(){
36         if(state == HAS_QUARTER){
37             System.out.println("退回25分");
38             state = NO_QUARTER;
39         }
40         else if(state == NO_QUARTER){
41             System.out.println("您并未投钱");
42         }
43         else if(state == SOLD_OUT){
44             System.out.println("您并未投钱");
45         }
46         else if(state == SOLD){
47             System.out.println("已经在出糖果,无法退钱");
48         }
49     }
50     //转动手柄
51     public void turnCrank(){
52         if(state == HAS_QUARTER){
53             System.out.println("您转动了手柄");
54             state = SOLD;
55             dispense();
56         }
57         else if(state == NO_QUARTER){
58             System.out.println("请先投钱再转动手柄");
59         }
60         else if(state == SOLD_OUT){
61             System.out.println("您并未投钱");
62         }
63         else if(state == SOLD){
64             System.out.println("已经给您糖果了,哼,别想骗我");
65         }
66     }
67     //发放糖果
68     private void dispense() {
69         if(state == HAS_QUARTER){
70             System.out.println("no gumball dispense");
71         }
72         else if(state == NO_QUARTER){
73             System.out.println("请先投钱");
74         }
75         else if(state == SOLD_OUT){
76             System.out.println("no gumball dispense");
77         }
78         else if(state == SOLD){
79             count = count - 1;
80             if(count ==0){
81                 System.out.println("最后 一颗糖果!");
82                 state = SOLD_OUT;
83             }else{
84                 System.out.println("给您糖果!");
85                 state = NO_QUARTER;
86             }
87         }
88     }     
89 }

2.万能糖果机要添加一种游戏:当个赢家!十个人中有1个人可以得到赠送的一颗糖果(也就是说,当曲柄转动时,有10%的机率掉下来的是两颗糖果)。

问题来了:照刚刚的写法,我们首先要添加一个赢家状态,然后再每一个方法中,加入一个新的条件判断来处理“赢家”状态,尤其是turnCrank,因为你必须坚持目前是否"赢家",然后再决定是切换到赢家状态还是售出糖果状态。

解决办法:局部化每个状态的行为,将每个状态的行为都放在各自的类中,那么每个状态都只需要实现自己的动作。

(1)定义一个state接口,在这个接口里,糖果机的每个动作都有一个对应的方法。

(2)为每个状态实现状态类,这些类负责对应状态下机器的行为。

(3)摆脱条件判断代码,将动作委托到状态类。

1 public interface State {
2     public void insertQuater();
3     public void ejectQuater();
4     public void turnCrank();
5     public void dispense();
6 }
 1 public class GumballMachine {
 2     State soldOutState;
 3     State soldState;
 4     State hasQuarterState;
 5     State noQuarterState;
 6      
 7     State state = soldOutState;
 8     int count = 0;
 9     
10     public GumballMachine(int count) {
11         super();
12         soldOutState = new SoldOutState(this);
13         soldState = new SoldState(this);
14         hasQuarterState = new HasQuarterState(this);
15         noQuarterState = new NoQuarterState(this);
16         this.count = count;
17         //如果库存不为0,就会进入“没有25分”,来等待别人投钱。否则就进入“售罄”,无法投钱
18         if(count>0){
19             state = noQuarterState;
20         }
21     }
22     //投钱
23     public void insertQuater(){
24         state.insertQuater();
25     }
26     //退钱
27     public void ejectQuater(){
28         state.ejectQuater();
29     }
30     //转动手柄
31     public void turnCrank(){
32         state.turnCrank();
33         state.dispense();
34     }
35     public void setState(State state) {
36         this.state = state;
37     }
38     
39     void releasBall(){
40         System.out.println("糖果正在滚出来的路上");
41         if(count!=0){
42             count = count-1;
43         }
44     }
45     public State getSoldOutState() {
46         return soldOutState;
47     }
48     public State getSoldState() {
49         return soldState;
50     }
51     public State getHasQuarterState() {
52         return hasQuarterState;
53     }
54     public State getNoQuarterState() {
55         return noQuarterState;
56     }
57 }
 1 public class SoldState implements State {
 2 
 3     GumballMachine gumballMachine;
 4     
 5     public SoldState(GumballMachine gumballMachine) {
 6         super();
 7         this.gumballMachine = gumballMachine;
 8     }
 9 
10     public void dispense() {
11         gumballMachine.releasBall();
12         if(gumballMachine.getCount()>0){
13             gumballMachine.setState(gumballMachine.getNoQuarterState());
14         }else{
15             System.out.println("卖完了");
16             gumballMachine.setState(gumballMachine.getSoldOutState());
17         }
18     }
19 
20     public void ejectQuater() {
21         System.out.println("准备发糖,无法退钱");
22     }
23 
24     public void insertQuater() {
25         System.out.println("请等糖出完");
26     }
27 
28     public void turnCrank() {
29         System.out.println("已经在出糖,不用转动手柄了");
30     }
31 
32 }

3.别忘了,我们游戏还没完成呢:

待续。

headFirst学习笔记之十:状态模式(5.2)

标签:

原文地址:http://www.cnblogs.com/liyuhui21310122/p/4471490.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!