状态模式

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

状态模式将一个类的实例对象的状态封装成为独立的类,并把类的动作委托到代表当前状态的类去实现。这样当对象的状态发生改变时,这个对象就会呈现不同的动作表现。

类图:

糖果售卖机具有四种状态:没有25分钱状态,有25分钱状态,售出糖果状态,糖果售罄状态
在糖果售卖机处于不同的状态下,糖果售卖机的动作表现不同。如在没有25分钱的状态下,投入25分钱的动作是合法的,在售出糖果的状态下,投入25分钱的动作是不合法的。
这时,就要更具售卖机对象处于不同的状态,来输出不同的语句。

状态接口  State接口

 1 /**
 2  * 这是糖果售卖机的状态接口  State
 3  * 糖果售卖机具有四种状态:没有25分钱状态,有25分钱状态,售出糖果状态,糖果售罄状态
 4  * 糖果售卖机 提供三个接口 给顾客调用  :投入25分钱,退出25分钱,转动曲柄(相当于确认购买)
 5  * 糖果售卖机 有一个接口 给自己调用:发放糖果 
 6  * @author wly
 7  *
 8  */
 9 public interface State {
10      /**
11       * 投入25分钱  的方法
12       */
13      public  void  insertQuarter();
14      /**
15       * 退出25分钱  的方法     
16       */
17      public  void  ejectQuarter();
18      /**
19       * 转动曲柄 确认购买 的方法
20       */
21      public  void  turnCrank();
22      /**
23       * 发放糖果 的方法
24       */
25      public void dispense();
26 }

 糖果售卖机  GumballMachine类

  1 /**
  2  * 这是糖果售卖机   GumballMachine类
  3  * @author wly
  4  *
  5  */
  6 public class GumballMachine {
  7     //声明一个变量,来引用 没有25分钱状态对象
  8     private   NoQuarterState  noQuarterState;
  9     //声明一个变量,来引用 有25分钱状态对象
 10     private   HasQuarterState hasQuarterState;
 11     //声明一个变量,来引用 售卖状态对象
 12     private   SoldState       soldState;
 13     //声明一个变量,来引用 售罄状态对象
 14     private   SoldOutState    soldOutState;
 15     //声明一个变量 ,  来表示 当前糖果售卖机 是处于 哪一种状态   新的糖果机处于售罄状态(因为没有糖果)
 16     private   State   state = soldOutState;
 17     //声明一个变量 , 表示 糖果的剩余数量
 18     private   int count;
 19     /**
 20      * 糖果售卖机的构造器      
 21      * @param count
 22      */
 23     public GumballMachine(int count)
 24     {
 25         //为糖果售卖机 创建四种状态对象   并把糖果售卖机的对象引用传给状态对象
 26         this.noQuarterState  =  new NoQuarterState(this);
 27         this.hasQuarterState =  new HasQuarterState(this);
 28         this.soldState       =  new SoldState(this);
 29         this.soldOutState    =  new SoldOutState(this);
 30         this.count  = count;
 31         //如果 传入的糖果数量大于0  让糖果售卖机  到 没有25分钱的状态
 32         if(count > 0 )
 33         {
 34             this.setState(noQuarterState);
 35         }
 36     }
 37     /**
 38      * 用来设置糖果售卖机当前状态对象的 setter方法
 39      * @param state
 40      */
 41     public void setState(State state)
 42     {
 43         this.state = state;
 44     }
 45     /**
 46      * 发出一个糖果  ,糖果剩余数量减1
 47      */
 48     public void realseBall()
 49     {
 50         if(count > 0)
 51         {
 52             count--;
 53         }
 54         System.out.println("一个糖果已经发出...还剩"+count+"个糖果");
 55     }
 56     //放入25分钱 的方法 让已经持有糖果机对象的状态对象去处理
 57     public void insertQuarter() {
 58         state.insertQuarter();
 59     }
 60     //退回25分钱 的方法 让已经持有糖果机对象的状态对象去处理
 61     public void ejectQuarter() {
 62         state.ejectQuarter();
 63      }
 64     //转动曲柄 的方法 让已经持有糖果机对象的状态对象去处理
 65     public void turnCrank() {
 66         state.turnCrank();
 67         //现在糖果机处于售卖状态  会自动调用dispense()方法 来发放糖果
 68         state.dispense();
 69     }
 70     //以下是 四种状态对象 和  糖果剩余数量对象的  getter方法 和 setter方法
 71     public NoQuarterState getNoQuarterState() {
 72         return noQuarterState;
 73     }
 74     public void setNoQuarterState(NoQuarterState noQuarterState) {
 75         this.noQuarterState = noQuarterState;
 76     }
 77     public HasQuarterState getHasQuarterState() {
 78         return hasQuarterState;
 79     }
 80     public void setHasQuarterState(HasQuarterState hasQuarterState) {
 81         this.hasQuarterState = hasQuarterState;
 82     }
 83     public SoldState getSoldState() {
 84         return soldState;
 85     }
 86     public void setSoldState(SoldState soldState) {
 87         this.soldState = soldState;
 88     }
 89     public SoldOutState getSoldOutState() {
 90         return soldOutState;
 91     }
 92     public void setSoldOutState(SoldOutState soldOutState) {
 93         this.soldOutState = soldOutState;
 94     }
 95     public int getCount() {
 96         return count;
 97     }
 98     public void setCount(int count) {
 99         this.count = count;
100     }
101     
102 } 

 没有25分钱状态 NoQuarterState类

 1 /**
 2  * 这是没有25分钱状态  NoQuarterState类 
 3  * 没有25分钱状态下  只有 放入钱的方法可用  可以引起状态改变
 4  * @author wly
 5  *
 6  */
 7 public class NoQuarterState implements State {
 8     //声明一个变量 ,来引用糖果售卖机对象
 9     private GumballMachine  gm;
10     public NoQuarterState(GumballMachine gm)
11     {
12         this.gm = gm;
13     }
14     @Override
15     public void insertQuarter() {
16         System.out.println("你已经放入了25分钱...");
17         //改变糖果售卖机的状态  到 有25分钱的状态
18         gm.setState(gm.getHasQuarterState());
19     }
20     
21     @Override
22     public void ejectQuarter() {
23         System.out.println("你还没有放入钱,不能要求退钱...");
24     }
25     
26     @Override
27     public void turnCrank() {
28         System.out.println("你还没有放入钱,不能转动曲柄...");
29     }
30     
31     @Override
32     public void dispense() {
33        System.out.println("你还没有放入钱,不能发放糖果...");
34     }
35 
36 }

 有25分钱的状态 HasQuarterState类

 1 /**
 2  * 这是有25分钱的状态   HasQuarterState类 
 3  * 在有25分钱的状态下  可以使用 退回钱的方法  从而让糖果售卖机的状态回到   没有25分钱状态
 4  * 可以使用 转动曲柄的方法  让糖果售卖机的状态前进到   售卖状态
 5  * @author wly
 6  *
 7  */
 8 public class HasQuarterState implements State {
 9     //声明一个变量 ,来引用糖果售卖机对象
10     private  GumballMachine  gm;
11     public  HasQuarterState(GumballMachine gm)
12     {
13         this.gm = gm;
14     }
15     @Override
16     public void insertQuarter() {
17         System.out.println("你已经放入了钱,不能再放入钱...");
18     }
19     
20     @Override
21     public void ejectQuarter() {
22         System.out.println("钱将退回给你...");
23         //改变糖果售卖机的状态  到  没有25分钱的状态
24         gm.setState(gm.getNoQuarterState());
25     }
26     
27     @Override
28     public void turnCrank() {
29         System.out.println("转动曲柄...");
30         //改变糖果售卖机的状态  到  售卖的状态
31         gm.setState(gm.getSoldState());
32     }
33     
34     @Override
35     public void dispense() {
36         System.out.println("糖果暂时不能发放...");
37     }
38 
39 }

 售卖的状态 SoldState类

 1 /**
 2  * 这是售卖的状态   SoldState类 
 3  * 售卖状态的 糖果发放方法 调用之后   根据当前的糖果数量  来决定 到到哪个状态
 4  * @author wly
 5  *
 6  */
 7 public class SoldState implements State {
 8     //声明一个变量 ,来引用糖果售卖机对象
 9     private GumballMachine  gm;
10     public SoldState(GumballMachine gm)
11     {
12         this.gm = gm;
13     }
14      
15     @Override
16     public void insertQuarter() {
17        System.out.println("请稍等,上一次的购买还在发放中,现在不能放入钱...");
18     }
19     
20     @Override
21     public void ejectQuarter() {
22        System.out.println("你已经转动曲柄,确认购买了,不能退钱了...");
23     }
24     
25     @Override
26     public void turnCrank() {
27        System.out.println("曲柄已经转动了,不能转动两次...");
28     }
29     
30     @Override
31     public void dispense() {
32          System.out.println("发放糖果中...");
33          //发放糖果的方法,糖果数量减1
34          gm.realseBall();
35          //如果糖果售卖机中的 糖果数量  大于0 糖果售卖机的状态 到 没有25分钱的状态
36          if(gm.getCount() > 0)
37          {
38              gm.setState(gm.getNoQuarterState());
39          }
40          else  //如果糖果售卖机中的 糖果数量  小于等于0 糖果售卖机的状态 到 售罄状态 
41          {
42              System.out.println("糖果已经售罄...");
43              gm.setState(gm.getSoldOutState());
44          }
45     }
46 
47 }
糖果售罄状态   SoldOutState类
 1 /**
 2  * 这是糖果售罄状态   SoldOutState类
 3  * @author wly
 4  *
 5  */
 6 public class SoldOutState implements State{
 7     //声明一个变量 ,来引用糖果售卖机对象
 8     private GumballMachine  gm;
 9     public SoldOutState(GumballMachine gm)
10     {
11         this.gm = gm;
12     }
13     @Override
14     public void insertQuarter() {
15        System.out.println("糖果已经售罄,不能再放入钱...");
16     }
17     
18     @Override
19     public void ejectQuarter() {
20         System.out.println("糖果已经售罄,不能退回钱...");
21     }
22     
23     @Override
24     public void turnCrank() {
25         System.out.println("糖果已经售罄,不能转动曲柄...");
26     }
27     
28     @Override
29     public void dispense() {
30        System.out.println("糖果已经售罄,不能发放糖果...");
31     }
32 }
最后提供一个测试类:
 1 public class TestClass {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7          //创建一个糖果售卖机对象  ,并为这个糖果售卖机对象  放入5颗糖果
 8          //糖果售卖机  处于 没有25分钱状态
 9          GumballMachine gm = new GumballMachine(5);
10          //放入25分钱  , 糖果售卖机处于有25分钱状态
11          gm.insertQuarter();
12          //转动曲柄  ,糖果售卖机处于售卖状态 ,自动调用发放糖果方法,糖果售卖机 将处于没有25分钱状态
13          gm.turnCrank();
14          System.out.println("********************");
15          //放入25分钱  , 糖果售卖机处于有25分钱状态
16          gm.insertQuarter();
17          //退回25分钱 ,糖果售卖机处于没有25分钱状态
18          gm.ejectQuarter();
19          System.out.println("********************");
20          gm.insertQuarter();
21          gm.turnCrank();
22          System.out.println("********************");
23          gm.insertQuarter();
24          gm.turnCrank();
25          System.out.println("********************");
26          gm.insertQuarter();
27          gm.turnCrank();
28          System.out.println("********************");
29          //放入25分钱  , 糖果售卖机处于有25分钱状态
30          gm.insertQuarter();
31          //转动曲柄  ,糖果售卖机处于售卖状态 ,自动调用发放糖果方法,糖果售卖机 中的糖果数为0,糖果售卖机将到糖果售罄状态
32          gm.turnCrank();
33          
34     }
35 }
运行结果如下:


 
原文地址:https://www.cnblogs.com/wangliyue/p/4227820.html