設計模式之State

来源:互联网 发布:淘宝网首页女鞋冬 编辑:程序博客网 时间:2024/05/17 23:32

State的定義: 不同的狀態,不同的行爲;或者說,每個狀態有著相應的行爲。

何時使用?
State
模式在實際使用中比較多,適合"狀態的切換"。因爲我們經常會使用If elseif else 進行狀態切換, 如果針對狀態的這樣判斷切換反復出現,我們就要聯想到是否可以採取State模式了。

不只是根據狀態,也有根據屬性。如果某個物件的屬性不同,物件的行爲就不一樣,這點在資料庫系統中出現頻率比較高,我們經常會在一個資料表的尾部,加上property屬性含義的欄位,用以標識記錄中一些特殊性質的記錄,這種屬性的改變(切換)又是隨時可能發生的,就有可能要使用State

是否使用?
在實際使用,類似開關一樣的狀態切換是很多的,但有時並不是那麽明顯,取決於你的經驗和對系統的理解深度。

這裏要闡述的是"開關切換狀態" " 一般的狀態判斷"是有一些區別的, " 一般的狀態判斷"也是有 if..elseif結構,例如:

    if (which==1) state="hello";
    
else if (which==2) state="hi";
    else if (which==3) state="bye";

這是一個 " 一般的狀態判斷",state值的不同是根據which變數來決定的,whichstate沒有關係。如果改成:

    if (state.euqals("bye")) state="hello";
    
else if (state.euqals("hello")) state="hi";
    else if (state.euqals("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==Color.red) state=Color.blue;

    //如果當前blue狀態 就切換到
green
    
else if (state==Color.blue) state=Color.green;

    //如果當前black狀態 就切換到
red
    
else if (state==Color.black) state=Color.red;

    //如果當前green狀態 就切換到
black
    
else if (state==Color.green) state=Color.black;
    

    Sample sample=new Sample(state);
    
sample.operate();
  }

  public void pull(){

    //push狀態切換正好相反

    if (state==Color.green) state=Color.blue;
    
else if (state==Color.black) state=Color.green;
    
else if (state==Color.blue) state=Color.red;
    
else if (state==Color.red) state=Color.black;

    
Sample2 sample2=new Sample2(state);
    
sample2.operate();
  }

}

在上例中,我們有兩個動作push推和pull,這兩個開關動作,改變了Context顔色,至此,我們就需要使用State模式優化它。

另外注意:但就上例,state的變化,只是簡單的顔色賦值,這個具體行爲是很簡單的,State適合巨大的具體行爲,因此在,就本例,實際使用中也不一定非要使用State模式,這會增加子類別的數目,簡單的變複雜。

例如: 銀行帳戶, 經常會在Open 狀態和Close狀態間轉換。

例如: 經典的TcpConnection, Tcp的狀態有創建 偵聽 關閉三個,並且反復轉換,其創建 偵聽 關閉的具體行爲不是簡單一兩句就能完成的,適合使用State

例如:信箱POP帳號, 會有四種狀態, start HaveUsername Authorized quit,每個狀態對應的行爲應該是比較大的.適合使用State

例如:在工具箱挑選不同工具,可以看成在不同工具中切換,適合使用State。如 具體繪圖程式,用戶可以選擇不同工具繪製方框 直線 曲線,這種狀態切換可以使用State

如何使用
State
需要兩種類型實體參與:

1.state manager 狀態管理器 ,就是開關 ,如上面例子的Context實際就是一個state manager, state manager中有對狀態的切換動作。
2.
用抽象類別或介面實現的父類別,,不同狀態就是繼承這個父類別的不同子類別。

以上面的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(); 同時還需要一個獲取pushpull結果的方法getcolor()

下面是具體子類別的實現:

public class BlueState extends State{

  public void handlepush(Context c){
     //根據push方法"如果是blue狀態的切換到
green" ;
     c.setState(new GreenState());

  }
  public void handlepull(Context c){

     //根據pull方法"如果是blue狀態的切換到red" ;
    c.setState(new RedState());

  }

  public abstract void getcolor(){ return (Color.blue)}

}

 

同樣 其他狀態的子類別實現如blue一樣。

第二步: 要重新改寫State manager 也就是本例的Context:

public class Context{

  private Sate state=null; //我們將原來的 Color state 改成了新建的State state;

  //setState是用來改變state的狀態 使用setState實現狀態的切換
  pulic void setState(State state){

    this.state=state;

  }

  public void push(){

    //狀態的切換的細節部分,在本例中是顔色的變化,已經封裝在子類別的handlepush中實現,這裏無需關心
    state.handlepush(this);
    

    //因爲sample要使用state中的一個切換結果,使用getColor()
    
Sample sample=new Sample(state.getColor());
    sample.operate();

  }

 

  public void pull(){

    state.handlepull(this);
    

    Sample2 sample2=new Sample2(state.getColor());
    sample2.operate();

  }

}

 

至此,我們也就實現了Staterefactorying過程。

以上只是相當簡單的一個實例,在實際應用中,handlepushhandelpull的處理是複雜的。


 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 棋牌app涉赌怎么办 打闲来麻将老输怎么办 儿子欠老子钱不还怎么办 傲风电竞椅扶手坏了怎么办 桑蚕丝面料发黄了怎么办? 天然植物纤维面料发黄怎么办 阴阳师吸血姬血太厚了怎么办 电话被骗了钱怎么办 镇魔曲元宝被扣怎么办 镇魔曲以前的角色怎么办 镇魔曲手游转职后装备怎么办 镇魔曲个性标签任务怎么办 教师资格证申请表打不开怎么办 怎么办appstore换到日本 电脑内存太小怎么办 win10声音卡顿怎么办 录音播放卡顿怎么办 笔记本电脑玩dnf卡怎么办 龙之谷约惠码被删了怎么办 天涯明月刀马没有了怎么办 icloud照片无法同步怎么办 ipad不能下载app怎么办 ipad屏幕孔进水怎么办 ipad无法验证登录怎么办 dnf电脑配置低怎么办 淘宝直播粉丝不够怎么办 电脑页面显示不全怎么办 脸上发痒长痘怎么办 扣扣魔性表情泡泡消失怎么办 脚起小泡泡很痒怎么办 孕妇脚痒起水泡怎么办 孕妇手脚起湿疹怎么办 嘴巴破皮了怎么办 小便刺痛阴唇红肿怎么办 集成墙面挂照片怎么办 苹果电脑网页游戏打不开怎么办 苹果6plus发热怎么办 玩手游手机太卡怎么办 苹果七发烫厉害怎么办 苹果手机延迟高怎么办 王者荣耀总是卡怎么办