亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

設計模式 狀態模式 以自動售貨機為例

2019-11-06 06:51:42
字體:
來源:轉載
供稿:網友

狀態模式給了我眼前一亮的感覺啊,值得學習~

先看定義:允許對象在內部狀態改變時改變它的行為,對象看起來好像修改了它的類。定義又開始模糊了,理一下,當對象的內部狀態改變時,它的行為跟隨狀態的改變而改變了,看起來好像重新初始化了一個類似的。

下面使用個例子來說明狀態模式的用法,現在有個自動售貨機的代碼需要我們來寫,狀態圖如下:

分析一個這個狀態圖:

a、包含4個狀態(我們使用4個int型常量來表示)

b、包含3個暴露在外的方法(投幣、退幣、轉動手柄)

c、我們需要處理每個狀態下,用戶都可以觸發這三個動作。

下面我們根據分析的結果,寫出代碼:

package com.zhy.pattern.status;    /**  * 自動售貨機  *   * @author zhy  *   */  public class VendingMachine  {        /**      * 已投幣      */      PRivate final static int HAS_MONEY = 0;      /**      * 未投幣      */      private final static int NO_MONEY = 1;      /**      * 售出商品      */      private final static int SOLD = 2;      /**      * 商品售罄      */      private final static int SOLD_OUT = 3;        private int currentStatus = NO_MONEY;      /**      * 商品數量      */      private int count = 0;        public VendingMachine(int count)      {          this.count = count;          if (count > 0)          {              currentStatus = NO_MONEY;          }      }        /**      * 投入硬幣,任何狀態用戶都可能投幣      */      public void insertMoney()      {          switch (currentStatus)          {          case NO_MONEY:              currentStatus = HAS_MONEY;              System.out.println("成功投入硬幣");              break;          case HAS_MONEY:              System.out.println("已經有硬幣,無需投幣");              break;          case SOLD:              System.out.println("請稍等...");              break;          case SOLD_OUT:              System.out.println("商品已經售罄,請勿投幣");              break;            }      }        /**      * 退幣,任何狀態用戶都可能退幣      */      public void backMoney()      {          switch (currentStatus)          {          case NO_MONEY:              System.out.println("您未投入硬幣");              break;          case HAS_MONEY:              currentStatus = NO_MONEY;              System.out.println("退幣成功");              break;          case SOLD:              System.out.println("您已經買了糖果...");              break;          case SOLD_OUT:              System.out.println("您未投幣...");              break;          }      }        /**      * 轉動手柄購買,任何狀態用戶都可能轉動手柄      */      public void turnCrank()      {          switch (currentStatus)          {          case NO_MONEY:              System.out.println("請先投入硬幣");              break;          case HAS_MONEY:              System.out.println("正在出商品....");              currentStatus = SOLD;              dispense();              break;          case SOLD:              System.out.println("連續轉動也沒用...");              break;          case SOLD_OUT:              System.out.println("商品已經售罄");              break;            }      }        /**      * 發放商品      */      private void dispense()      {            switch (currentStatus)          {          case NO_MONEY:          case HAS_MONEY:          case SOLD_OUT:              throw new IllegalStateException("非法的狀態...");          case SOLD:              count--;              System.out.println("發出商品...");              if (count == 0)              {                  System.out.println("商品售罄");                  currentStatus = SOLD_OUT;              } else              {                  currentStatus = NO_MONEY;              }              break;            }        }  }  針對用戶的每個動作,我們考慮了在任何狀態下發生,并做了一定處理。下面進行一些測試:
package com.zhy.pattern.status;    public class TestTra  {      public static void main(String[] args)      {          VendingMachine machine = new VendingMachine(10);          machine.insertMoney();          machine.backMoney();            System.out.println("-----------");            machine.insertMoney();          machine.turnCrank();                    System.out.println("----------壓力測試-----");          machine.insertMoney();          machine.insertMoney();          machine.turnCrank();          machine.turnCrank();          machine.backMoney();          machine.turnCrank();        }  }  輸出結果:

成功投入硬幣  退幣成功  -----------  成功投入硬幣  正在出商品....  發出商品...  ----------壓力測試-----  成功投入硬幣  已經有硬幣,無需投幣  正在出商品....  發出商品...  請先投入硬幣  您未投入硬幣  請先投入硬幣  感覺還是不錯的,基本實現了功能,但是有些事情是不可避免的,那就是需求的變化,現在為了提升銷量,當用戶每次轉動手柄買商品的時候,有10%的幾率贈送一瓶。

現在的狀態圖發生了變化,當用戶轉動手柄時,可能會達到一個中獎的狀態:圖如下:

如果在我們剛寫的代碼上直接添加,則需要在每個動作的switch中添加判斷條件,且非常容易出錯。所以現在我們要考慮重新設計我們的代碼,我們考慮把每個狀態寫狀態類,負責實現在對應動作下的行為,然后自動售貨機在不能的狀態間切換:

下面開始重構,我們現在有5種狀態,對應4個動作(投幣、退幣、轉動手柄、發出商品),下面首先定義一個狀態的超類型:

package com.zhy.pattern.status.b;    /**  * 狀態的接口  * @author zhy  *  */  public interface State  {      /**      * 放錢      */      public void insertMoney();      /**      * 退錢      */      public void backMoney();      /**      * 轉動曲柄      */      public void turnCrank();      /**      * 出商品      */      public void dispense();  }  然后分別是每個狀態的實現:

package com.zhy.pattern.status.b;    /**  * 沒錢的狀態  * @author zhy  *  */  public class NoMoneyState implements State  {        private VendingMachine machine;        public NoMoneyState(VendingMachine machine)      {          this.machine = machine;                }            @Override      public void insertMoney()      {          System.out.println("投幣成功");          machine.setState(machine.getHasMoneyState());      }        @Override      public void backMoney()      {          System.out.println("您未投幣,想退錢?...");      }        @Override      public void turnCrank()      {          System.out.println("您未投幣,想拿東西么?...");      }        @Override      public void dispense()      {          throw new IllegalStateException("非法狀態!");      }    }  

package com.zhy.pattern.status.b;    import java.util.Random;    /**  * 已投入錢的狀態  *   * @author zhy  *   */  public class HasMoneyState implements State  {        private VendingMachine machine;      private Random random = new Random();        public HasMoneyState(VendingMachine machine)      {          this.machine = machine;      }        @Override      public void insertMoney()      {          System.out.println("您已經投過幣了,無需再投....");      }        @Override      public void backMoney()      {          System.out.println("退幣成功");            machine.setState(machine.getNoMoneyState());      }        @Override      public void turnCrank()      {          System.out.println("你轉動了手柄");          int winner = random.nextInt(10);          if (winner == 0 && machine.getCount() > 1)          {              machine.setState(machine.getWinnerState());          } else          {              machine.setState(machine.getSoldState());          }      }        @Override      public void dispense()      {          throw new IllegalStateException("非法狀態!");      }    }  

package com.zhy.pattern.status.b;    /**  * 售罄的狀態  *   * @author zhy  *   */  public class SoldOutState implements State  {        private VendingMachine machine;        public SoldOutState(VendingMachine machine)      {          this.machine = machine;      }        @Override      public void insertMoney()      {          System.out.println("投幣失敗,商品已售罄");      }        @Override      public void backMoney()      {          System.out.println("您未投幣,想退錢么?...");      }        @Override      public void turnCrank()      {          System.out.println("商品售罄,轉動手柄也木有用");      }        @Override      public void dispense()      {          throw new IllegalStateException("非法狀態!");      }    }  

package com.zhy.pattern.status.b;    /**  * 準備出商品的狀態,該狀態下,不會有任何用戶的操作  *   * @author zhy  *   */  public class SoldState implements State  {        private VendingMachine machine;        public SoldState(VendingMachine machine)      {          this.machine = machine;      }        @Override      public void insertMoney()      {          System.out.println("正在出貨,請勿投幣");      }        @Override      public void backMoney()      {          System.out.println("正在出貨,沒有可退的錢");      }        @Override      public void turnCrank()      {          System.out.println("正在出貨,請勿重復轉動手柄");      }        @Override      public void dispense()      {          machine.dispense();          if (machine.getCount() > 0)          {              machine.setState(machine.getNoMoneyState());          } else          {              System.out.println("商品已經售罄");              machine.setState(machine.getSoldOutState());          }      }  }  

package com.zhy.pattern.status.b;    /**  * 中獎的狀態,該狀態下不會有任何用戶的操作  *   * @author zhy  *   */  public class WinnerState implements State  {        private VendingMachine machine;        public WinnerState(VendingMachine machine)      {          this.machine = machine;      }        @Override      public void insertMoney()      {          throw new IllegalStateException("非法狀態");      }        @Override      public void backMoney()      {          throw new IllegalStateException("非法狀態");      }        @Override      public void turnCrank()      {          throw new IllegalStateException("非法狀態");      }        @Override      public void dispense()      {          System.out.println("你中獎了,恭喜你,將得到2件商品");          machine.dispense();            if (machine.getCount() == 0)          {              System.out.println("商品已經售罄");              machine.setState(machine.getSoldOutState());          } else          {              machine.dispense();              if (machine.getCount() > 0)              {                  machine.setState(machine.getNoMoneyState());              } else              {                  System.out.println("商品已經售罄");                  machine.setState(machine.getSoldOutState());              }                        }        }    }  

最后是自動售貨機的代碼:

package com.zhy.pattern.status.b;    /**  * 自動售貨機  *   * @author zhy  *   */  public class VendingMachine  {      private State noMoneyState;      private State hasMoneyState;      private State soldState;      private State soldOutState;      private State winnerState ;         private int count = 0;      private State currentState = noMoneyState;        public VendingMachine(int count)      {          noMoneyState = new NoMoneyState(this);          hasMoneyState = new HasMoneyState(this);          soldState = new SoldState(this);          soldOutState = new SoldOutState(this);          winnerState = new WinnerState(this);            if (count > 0)          {              this.count = count;              currentState = noMoneyState;          }      }        public void insertMoney()      {          currentState.insertMoney();      }        public void backMoney()      {          currentState.backMoney();      }        public void turnCrank()      {          currentState.turnCrank();          if (currentState == soldState || currentState == winnerState)              currentState.dispense();      }        public void dispense()      {          System.out.println("發出一件商品...");          if (count != 0)          {              count -= 1;          }      }        public void setState(State state)      {          this.currentState = state;      }        //getter setter omitted ...    }  可以看到,我們現在把每個狀態對應于動作的行為局部化到了狀態自己的類中實現,不僅增加了擴展性而且使代碼的閱讀性大幅度的提高。以后再添加狀態,只需要針對新添加的狀態的實現類,并在自動售貨機中添加此狀態即可。

下面進行一些測試:

package com.zhy.pattern.status.b;    public class Test  {      public static void main(String[] args)      {          VendingMachine machine = new VendingMachine(10);          machine.insertMoney();          machine.backMoney();            System.out.println("----我要中獎----");            machine.insertMoney();          machine.turnCrank();          machine.insertMoney();          machine.turnCrank();          machine.insertMoney();          machine.turnCrank();          machine.insertMoney();          machine.turnCrank();          machine.insertMoney();          machine.turnCrank();          machine.insertMoney();          machine.turnCrank();          machine.insertMoney();          machine.turnCrank();            System.out.println("-------壓力測試------");            machine.insertMoney();          machine.backMoney();          machine.backMoney();          machine.turnCrank();// 無效操作          machine.turnCrank();// 無效操作          machine.backMoney();        }  }  輸出結果:

投幣成功  退幣成功  ----我要中獎----  投幣成功  你轉動了手柄  發出一件商品...  投幣成功  你轉動了手柄  發出一件商品...  投幣成功  你轉動了手柄  發出一件商品...  投幣成功  你轉動了手柄  發出一件商品...  投幣成功  你轉動了手柄  發出一件商品...  投幣成功  你轉動了手柄  發出一件商品...  投幣成功  你轉動了手柄  你中獎了,恭喜你,將得到2件商品  發出一件商品...  發出一件商品...  -------壓力測試------  投幣成功  退幣成功  您未投幣,想退錢?...  您未投幣,想拿東西么?...  您未投幣,想拿東西么?...  您未投幣,想退錢?...  恭喜你,又學會了一個設計模式,狀態模式。最后看下狀態模式的類圖:


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美精品一区二区| 日韩精品在线免费观看视频| 国产成人涩涩涩视频在线观看| 午夜精品久久久久久99热软件| 亚洲最新av在线| 亚洲欧洲国产一区| 日本久久久久久| 亚洲自拍高清视频网站| 欧美精品中文字幕一区| 久久精品视频在线观看| 国产精品99久久久久久久久久久久| 日韩av在线影院| 久热精品视频在线免费观看| 精品毛片网大全| 国内免费精品永久在线视频| 亚洲女人天堂网| 日韩午夜在线视频| 精品视频在线播放免| 亚洲欧美激情四射在线日| 日韩乱码在线视频| 91av成人在线| 亚洲精品免费网站| 在线免费观看羞羞视频一区二区| 亚洲一区av在线播放| 欧美成人自拍视频| 日韩福利伦理影院免费| 国语自产精品视频在免费| 成人性生交大片免费看小说| 中文字幕精品在线视频| 亚洲精品国产精品国自产观看浪潮| 久久精品99久久久香蕉| 亚洲韩国欧洲国产日产av| 亚洲国产精久久久久久久| 欧美老少配视频| 欧美日韩一区免费| 国产日本欧美一区| 欧美激情精品久久久久久免费印度| 欧美日韩国内自拍| 热久久美女精品天天吊色| 国产精品av在线| 97超视频免费观看| 在线观看久久久久久| 欧美在线性爱视频| zzjj国产精品一区二区| 欧美电影免费观看高清| 黄色成人在线播放| 欧美日韩在线观看视频小说| 亚洲曰本av电影| 欧美激情视频网站| 国产美女扒开尿口久久久| 国产精品旅馆在线| 国产视频久久久| 91国产中文字幕| 97婷婷大伊香蕉精品视频| 在线视频一区二区| 九九热精品视频在线播放| 国产精品久久久久久久久久| 91在线高清免费观看| 日韩中文在线不卡| 中文字幕亚洲无线码在线一区| 国产精品扒开腿做爽爽爽的视频| 国产一区二区三区网站| 国产精品久久久久77777| 81精品国产乱码久久久久久| 欧美性xxxx极品高清hd直播| 成人情趣片在线观看免费| 亚洲午夜未满十八勿入免费观看全集| 日韩色av导航| 久久香蕉国产线看观看网| 中文日韩在线观看| 亚洲人成电影在线观看天堂色| 在线播放日韩欧美| 中文字幕亚洲欧美日韩高清| 欧美日韩美女在线观看| 日本不卡免费高清视频| 欧美一级淫片aaaaaaa视频| 日韩欧美精品中文字幕| 国产精品亚洲激情| 欧美又大粗又爽又黄大片视频| 成人免费在线视频网站| 国产欧美日韩视频| 欧美第一黄网免费网站| 日韩电影在线观看免费| 精品国产一区二区三区久久久| 亚洲女同精品视频| 91在线观看免费| 欧美日韩一区二区在线| 69视频在线播放| 国产91精品久久久久久久| 在线观看中文字幕亚洲| 久久久www成人免费精品张筱雨| 2018国产精品视频| 国产人妖伪娘一区91| 日韩在线观看你懂的| 欧美日韩性生活视频| 亚洲第一区第二区| 国产精品高清在线| 91精品国产电影| 欧美裸体xxxx| 国产激情久久久| 精品久久久香蕉免费精品视频| 久久久久一本一区二区青青蜜月| 亚洲毛茸茸少妇高潮呻吟| 4438全国亚洲精品在线观看视频| 国产精品激情av电影在线观看| 久久九九有精品国产23| 国产欧美日韩中文字幕在线| 亚洲精品久久视频| 在线视频欧美日韩| 日韩小视频在线| 国产精品福利在线观看| 国产精品久久久久秋霞鲁丝| 国产婷婷色综合av蜜臀av| 亚洲欧美一区二区三区情侣bbw| 91地址最新发布| 国产欧美日韩亚洲精品| 欧美一乱一性一交一视频| 久久这里只有精品99| 91在线视频精品| 欧美日韩黄色大片| 91欧美精品午夜性色福利在线| 久久精品2019中文字幕| 国产欧美最新羞羞视频在线观看| 中日韩午夜理伦电影免费| 日韩成人中文字幕| www.国产精品一二区| 国产亚洲视频中文字幕视频| 亚洲天堂av电影| 欧美视频在线观看免费网址| 亚洲片在线观看| 色琪琪综合男人的天堂aⅴ视频| 国产一区二区三区日韩欧美| 日本午夜在线亚洲.国产| 日本aⅴ大伊香蕉精品视频| 国产精品丝袜视频| 久久伊人免费视频| 一本一本久久a久久精品牛牛影视| 久久久久999| 国产精品色婷婷视频| 日韩av在线最新| 亚洲伊人久久大香线蕉av| 国产视频观看一区| 欧美极品少妇与黑人| 欧美www在线| 日韩成人中文字幕| 最好看的2019的中文字幕视频| 最近2019中文字幕一页二页| 亚洲综合日韩中文字幕v在线| 欧美激情第1页| 亚洲韩国欧洲国产日产av| 岛国av一区二区| 欧美成人午夜剧场免费观看| 国产精品一区二区三区免费视频| 中文字幕日韩精品在线观看| 国产成人久久久| 91成品人片a无限观看| 欧美激情a∨在线视频播放| 日韩a**站在线观看| 国产成人一区二区三区电影| 亚洲电影中文字幕| 中文字幕av一区二区三区谷原希美| 欧美午夜www高清视频| 精品一区精品二区| 日韩精品免费综合视频在线播放|