熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

java設計模式之State(對應每種狀態的行為)

2013-11-23 19:49:55  來源: Java高級技術 

  State的定義: 不同的狀態不同的行為;或者說每個狀態有著相應的行為
  
  何時使用?
  State模式在實際使用中比較多適合狀態的切換因為我們經常會使用If elseif else 進行狀態切換 如果針對狀態的這樣判斷切換反復出現我們就要聯想到是否可以采取State模式了
  
  不只是根據狀態也有根據屬性如果某個對象的屬性不同對象的行為就不一樣這點在數據庫系統中出現頻率比較高我們經常會在一個數據表的尾部加上property屬性含義的字段用以標識記錄中一些特殊性質的記錄這種屬性的改變(切換)又是隨時可能發生的就有可能要使用State
  
  是否使用?
  在實際使用類似開關一樣的狀態切換是很多的但有時並不是那麼明顯取決於你的經驗和對系統的理解深度
  
  這裡要闡述的是開關切換狀態 一般的狀態判斷是有一些區別的 一般的狀態判斷也是有 ifelseif結構例如:
  
      if (which==) state=hello;
      else if (which==) state=hi;
      else if (which==) state=bye;
  
  這是一個 一般的狀態判斷state值的不同是根據which變量來決定的which和state沒有關系如果改成:
  
      if (stateeuqals(bye)) state=hello;
      else if (stateeuqals(hello)) state=hi;
      else if (stateeuqals(hi)) state=bye;
  
  這就是 開關切換狀態是將state的狀態從hello切換到hi再切換到bye;在切換到hello好象一個旋轉開關這種狀態改變就可以使用State模式了
  
  如果單純有上面一種將hello>hi>bye>hello這一個方向切換也不一定需要使用State模式因為State模式會建立很多子類復雜化但是如果又發生另外一個行為:將上面的切換方向反過來切換或者需要任意切換就需要State了
  
  請看下例:
  
  public class Context{
  
    private Color state=null;
  
    public void push(){
  
      //如果當前red狀態 就切換到blue
      if (state==Colorred) state=Colorblue;
  
      //如果當前blue狀態 就切換到green
      else if (state==Colorblue) state=Colorgreen;
  
      //如果當前black狀態 就切換到red
      else if (state==Colorblack) state=Colorred;
  
      //如果當前green狀態 就切換到black
      else if (state==Colorgreen) state=Colorblack;
      
      Sample sample=new Sample(state);
      sampleoperate();
    }
  
    public void pull(){
  
      //與push狀態切換正好相反
  
      if (state==Colorgreen) state=Colorblue;
      else if (state==Colorblack) state=Colorgreen;
      else if (state==Colorblue) state=Colorred;
      else if (state==Colorred) state=Colorblack;
  
      Sample sample=new Sample(state);
      sampleoperate();
    }
  
  }
  
  在上例中我們有兩個動作push推和pull拉這兩個開關動作改變了Context顏色至此我們就需要使用State模式優化它
  
  另外注意:但就上例state的變化只是簡單的顏色賦值這個具體行為是很簡單的State適合巨大的具體行為因此在就本例實際使用中也不一定非要使用State模式這會增加子類的數目簡單的變復雜
  
  例如: 銀行帳戶 經常會在Open 狀態和Close狀態間轉換
  
  例如: 經典的TcpConnection Tcp的狀態有創建 偵聽 關閉三個並且反復轉換其創建 偵聽 關閉的具體行為不是簡單一兩句就能完成的適合使用State
  
  例如:信箱POP帳號 會有四種狀態 start HaveUsername Authorized quit每個狀態對應的行為應該是比較大的適合使用State
  
  例如:在工具箱挑選不同工具可以看成在不同工具中切換適合使用State如 具體繪圖程序用戶可以選擇不同工具繪制方框 直線 曲線這種狀態切換可以使用State
  
  如何使用?
  State需要兩種類型實體參與:
  
  state manager 狀態管理器 就是開關 如上面例子的Context實際就是一個state manager 在state manager中有對狀態的切換動作
  用抽象類或接口實現的父類不同狀態就是繼承這個父類的不同子類
  
  以上面的Context為例我們要修改它建立兩個類型的實體
  第一步: 首先建立一個父類:
  
  public abstract class State{
  
    public abstract void handlepush(Context c);
    public abstract void handlepull(Context c);
    public abstract void getcolor();
  
  }
  
  父類中的方法要對應state manager中的開關行為在state manager中 本例就是Context中有兩個開關動作push推和pull拉那麼在狀態父類中就要有具體處理這兩個動作:handlepush() handlepull(); 同時還需要一個獲取push或pull結果的方法getcolor()
  
  下面是具體子類的實現:
  
  public class BlueState extends State{
  
    public void handlepush(Context c){
       //根據push方法如果是blue狀態的切換到green
       csetState(new GreenState());
  
    }
    public void handlepull(Context c){
  
       //根據pull方法如果是blue狀態的切換到red
      csetState(new RedState());
  
    }
  
    public abstract void getcolor(){ return (Colorblue)}
  
  }
  
  同樣 其他狀態的子類實現如blue一樣
  
  第二步: 要重新改寫State manager 也就是本例的Context:
  
  public class Context{
  
    private Sate state=null; //我們將原來的 Color state 改成了新建的State state;
  
    //setState是用來改變state的狀態 使用setState實現狀態的切換
    pulic void setState(State state){
  
      thisstate=state;
  
    }
  
    public void push(){
  
      //狀態的切換的細節部分在本例中是顏色的變化已經封裝在子類的handlepush中實現這裡無需關心
      statehandlepush(this);
      
      //因為sample要使用state中的一個切換結果使用getColor()
      Sample sample=new Sample(stategetColor());
      sampleoperate();
  
    }
  
    public void pull(){
  
      statehandlepull(this);
      
      Sample sample=new Sample(stategetColor());
      sampleoperate();
  
    }
  
  }
  
  至此我們也就實現了State的refactorying過程
  
  以上只是相當簡單的一個實例在實際應用中handlepush或handelpull的處理是復雜的
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27521.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.