多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 設計模式 —— 狀態模式(State Pattern)

設計模式 —— 狀態模式(State Pattern)

來源:程序員人生   發布時間:2016-06-08 08:26:22 閱讀次數:2786次

狀態模式(State Pattern)

概念:狀態模式 允許對象在內部狀態改變時改變它的行動,對象看起來好像修改了它的類


在軟件設計中,我們常常會遇需要編寫有很多狀態的程序。最簡單的如乘坐電梯程序,當我們要坐電梯時需要判斷電梯的狀態,只有當電梯處于當前樓時我們才能乘坐,當電梯不在當前樓層時我們要按下按鈕等待電梯到來。在平時1般都通過 if…elseswitch 判斷狀態后處理,這類固定的寫法只有在軟件后期不會更新時才可以(不過是不可能的),狀態模式實際上是使用組合通過簡單援用不同的狀態 對象 來造成狀態改變的假象。


組成:

狀態模式

Context(上下文):1般是1個具有多個狀態的類,當調用 request() 函數時會被拜托到狀態對象。

State(狀態接口):定義了所有具體狀態的共同接口,任何狀態都實現這個接口,這樣就可以在狀態之間相互轉換。

ConcreteStateA(具體狀態):實現狀態接口,處理來自 Context 的要求。每一個 ConcreteState 都提供自己要求的實現。


例子:

我們實現電梯的例子,電梯的狀態包括運行、停止、開門、關門。當電梯運行時我們等待電梯停止,停止時我們等待開門或運行,開門時進入后關門,進入后電梯變成關門狀態。

狀態模式

假定目前就這么多狀態,用傳統的 if…elseswitch 實現。

抽象狀態類

public abstract class LiftState { //4種狀態 final int OPEN_STATE = 1; final int STOP_STATE = 2; final int CLOSE_STATE = 3; final int RUN_STATE = 4; public abstract void setState(int state); //開門動作 public abstract void open(); //關門動作 public abstract void close(); //運行動作 public abstract void run(); //停止動作 public abstract void stop(); }

public class Lift extends LiftState{ private int state; public Lift(int state) { this.state = state; } @Override public void setState(int state) { this.state = state; } //開門動作 @Override public void open() { switch (state) { case OPEN_STATE: System.out.println("處于開門狀態:甚么也不做"); break; case CLOSE_STATE: System.out.println("處于關門狀態:甚么也不做"); break; case RUN_STATE: System.out.println("處于運行狀態:甚么也不做"); break; case STOP_STATE: System.out.println("處于關門狀態,開門..."); setState(OPEN_STATE); break; } } //關門動作 @Override public void close() { switch (state) { case OPEN_STATE: System.out.println("處于開門狀態:關門..."); setState(CLOSE_STATE); break; case CLOSE_STATE: System.out.println("處于關門狀態:甚么也不做"); break; case RUN_STATE: System.out.println("處于運行狀態:甚么也不做"); break; case STOP_STATE: System.out.println("處于停止狀態:甚么也不做"); break; } } //運行動作 @Override public void run() { switch (state) { case OPEN_STATE: System.out.println("處于開門狀態:甚么也不做"); break; case CLOSE_STATE: System.out.println("處于關門狀態:運行..."); setState(RUN_STATE); break; case RUN_STATE: System.out.println("處于運行狀態:甚么也不做"); break; case STOP_STATE: System.out.println("處于停止狀態:運行..."); setState(RUN_STATE); } } //停止動作 @Override public void stop() { switch (state) { case OPEN_STATE: System.out.println("處于開門狀態:甚么也不做"); break; case CLOSE_STATE: System.out.println("處于關門狀態:甚么也不做"); setState(CLOSE_STATE); break; case RUN_STATE: System.out.println("處于運行狀態:停止..."); break; case STOP_STATE: System.out.println("處于停止狀態:甚么也不做"); } } }

public class LiftRun { public static void main(String[] args) { //初始設置為停止狀態 Lift lift = new Lift(2); //停止變成運行 lift.run(); //運行時不能開門 lift.open(); //運行變成停止 lift.stop(); //停止時不能開門 lift.close(); } }

狀態模式

上面的實現沒甚么問題,但大量的用了 switch…case,當我們想要為電梯增加1種狀態時,會發現需要大量的改動代碼,每個 switch 都要改,這也是《重構》中稱 switch代碼的壞味道。我們來通過 狀態模式 改變它。


狀態模式改進例子:

狀態模式

LiftState:

public abstract class LiftState { Lift lift; public LiftState(Lift lift) { this.lift = lift; } //開門動作 public abstract void open(); //關門動作 public abstract void close(); //運行動作 public abstract void run(); //停止動作 public abstract void stop(); }

CloseState:

public class CloseState extends LiftState { public CloseState(Lift lift) { super(lift); } @Override public void open() { System.out.println("處于關閉狀態...甚么也不做"); } @Override public void close() { System.out.println("處于關閉狀態...甚么也不做"); } @Override public void run() { System.out.println("處于關閉狀態:運行"); lift.setState(lift.getRunState()); } @Override public void stop() { System.out.println("處于關閉狀態...甚么也不做"); } }

OpenState:

public class OpenState extends LiftState { public OpenState(Lift lift) { super(lift); } @Override public void open() { System.out.println("處于開門狀態...甚么也不錯"); } @Override public void close() { System.out.println("處于開門狀態:關門"); lift.setState(lift.getCloseState()); } @Override public void run() { System.out.println("處于開門狀態...甚么也不錯"); } @Override public void stop() { System.out.println("處于開門狀態...甚么也不錯"); } }

RunState:

public class RunState extends LiftState { public RunState(Lift lift) { super(lift); } @Override public void open() { System.out.println("處于運行狀態...甚么也不做"); } @Override public void close() { System.out.println("處于運行狀態...甚么也不做"); } @Override public void run() { System.out.println("處于運行狀態...甚么也不做"); } @Override public void stop() { System.out.println("處于運行狀態:停止"); lift.setState(lift.getStopState()); } }

StopState:

public class StopState extends LiftState { public StopState(Lift lift) { super(lift); } @Override public void open() { System.out.println("處于停止狀態:開門"); lift.setState(lift.getOpenState()); } @Override public void close() { System.out.println("處于停止狀態...甚么也不做"); } @Override public void run() { System.out.println("處于停止狀態:運行"); lift.setState(lift.getRunState()); } @Override public void stop() { System.out.println("處于停止狀態...甚么也不做"); } }

Lift:

public class Lift { LiftState openState; LiftState closeState; LiftState runState; LiftState stopState; LiftState state; public Lift() { openState = new OpenState(this); closeState = new CloseState(this); runState = new RunState(this); stopState = new StopState(this); //起始設置為停止狀態 state = stopState; } //拜托給狀態對象履行 public void stop() { state.stop(); } public void run() { state.run(); } public void close() { state.close(); } public void open() { state.open(); } //僅僅更換當前對象的援用 public void setState(LiftState state) { this.state = state; } public LiftState getOpenState() { return openState; } public LiftState getCloseState() { return closeState; } public LiftState getRunState() { return runState; } public LiftState getStopState() { return stopState; } }

LiftRun:

public class LiftRun { public static void main(String[] args) { //其實設置為停止狀態 Lift lift = new Lift(); lift.run(); lift.open(); lift.stop(); lift.close(); } }

運行結果:

狀態模式

通過狀態模式改進后,我們將每一個狀態和狀態行動封裝成了對象和方法,雖然增加了類的數目,但是當我們增加狀態時不用改動本來的代碼,僅需創建新的狀態實現接口的方法便可。

如增加故障狀態:

public class BugState extends LiftState { public BugState(Lift lift) { super(lift); } @Override public void open() { System.out.println("故障狀態,不能打開"); } @Override public void close() { System.out.println("故障狀態,不能關閉"); } @Override public void run() { System.out.println("故障狀態,不能運行"); } @Override public void stop() { System.out.println("故障狀態,停止..維修"); lift.setState(lift.getStopState()); } @Override public void bug() { System.out.println("故障狀態"); } }

在每一個狀態對象中加入相應的 bug 狀態函數,如:

@Override public void bug() { System.out.println("處于停止狀態:維修電梯"); lift.setState(lift.getBugState()); }

接著在 Lift 類中加入 bug 狀態:

LiftState bugState; ... //構造函數中 bugState = new BugState(this); ... public LiftState getBugState() { return bugState; }

測試函數:

public class LiftRun { public static void main(String[] args) { //其實設置為停止狀態 Lift lift = new Lift(); //運行 lift.run(); lift.bug(); lift.stop(); lift.run(); } }

狀態模式

處于狀態模式下僅僅需要新增1個類外加做1些小改動便可完成狀態的增加,大大方便了后期的保護和修改。

適用處景:

  • 1個對象的行動取決于它的狀態, 并且它必須在運行時刻根據狀態改變它的行動。
  • 代碼中包括大量與對象狀態有關的條件語句:1個操作中含有龐大的多分支的條件(if else 或switch case)語句,且這些分支依賴于該對象的狀態。這個狀態通經常使用1個或多個枚舉常量表示。通常 , 有多個操作包括這1相同的條件結構。 State模式將每個條件分支放入1個獨立的類中。這使得你可以根據對象本身的情況將對象的狀態作為1個對象,這1對象可以不依賴于其他對象而獨立變化。

優缺點:

優點:

  • 封裝了轉換規則,將所有與某個狀態有關的行動放到1個類中,并且可以方便地增加新的狀態,只需要改變對象狀態便可改變對象的行動。
  • 允許狀態轉換邏輯與狀態對象合成1體,而不是某1個巨大的條件語句塊。
  • 可讓多個環境對象同享1個狀態對象,從而減少系統中對象的個數。

缺點:

  • 狀態模式的使用必定會增加系統類和對象的個數。
  • 狀態模式的結構與實現都較為復雜,如果使用不當將致使程序結構和代碼的混亂。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 看一级黄色毛片 | 免费看w片的网站在线看 | 2021天天躁夜夜躁狠狠躁 | 亚洲第一免费视频 | 在线日韩麻豆一区 | 欧美亚洲尤物久久精品 | 亚洲人免费视频 | 亚洲精品自拍 | 亚洲福利片 | 三级小说第一页 | 欧美性受xxxx狂喷水 | 久久精品国产亚洲网址 | 亚洲成a人片在线v观看 | 大焦伊人| 亚洲最大的视频网站 | 日本一区二区高清免费不卡 | 久草福利视频 | 自由成熟的性色视频免费观看 | 精品一成人岛国片在线观看 | 国产成人高清 | 日韩精品久久久毛片一区二区 | 亚洲一区二区三区四区在线 | 日本一区二区在线播放 | 美日韩一区二区 | 国产精品乱码免费一区二区 | www.黄色一片 | 高清一区二区三区四区五区 | 日本a∨网站 | 久久亚洲天堂 | 亚洲免费精品视频 | 国内自拍视频网站 | 亚洲欧美视频一区二区 | 抖音毛片 | 欧美激情免费a视频 | 在线观看www日本免费网站 | 最近最新中文字幕大全2019免费视频 | 亚洲 欧美 都市 自拍 在线 | 久久a级片| 日韩欧美印度一级毛片 | 国产精品第二页 | 亚洲黄视频在线观看 |