设计模式之状态模式(State)
什么是狀態?
我們在購物網站進行購物時,訂單會產生幾種狀況:已下單、已付款、送貨中、確定收貨等狀態。
所以系統會判斷該訂單的狀態,不管是哪種狀態都應給出對應的操作,這就是狀態。
?什么是狀態模式?
在軟件開發過程中,應用程序可能會根據不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發生的情況全都考慮到。然后使用if... ellse語句來做狀態判斷來進行不同情況的處理。但是對復雜狀態的判斷就顯得“力不從心了”。隨著增加新的狀態或者修改一個狀體(if else(或switch case)語句的增多或者修改)可能會引起很大的修改,而程序的可讀性,擴展性也會變得很弱。維護也會很麻煩。這時就要考慮只修改自身狀態的模式。
?類圖
? ? ? ? ? ? ? ?
?模式的角色組成
1)環境角色(Context)
? ? ??客戶程序需要的接口,并且維護一個具體狀態的實例,這個實例決定當前狀態。
2)狀態角色(State)
? ? ??定義一個接口以封裝與使用環境角色的一個特定狀態的相關行為。
3)具體狀態角色(ConcreteState)
? ? ?實現狀態角色定義的接口,結構十分簡單與策略模式相似。
?狀態模式的特征
1)? 抽象狀態角色(State)
? ? ?定義一個接口用以封裝對象的一個特定狀態所對應的行為。
2)? 具體狀態(Concrete State)
? ? ? 一個具體的狀態的實現類實現了Context對象的一個狀態所對應的行為。
3) 環境角色(Context)
? ? ? 定義客戶端所感興趣的接口,并且保留一個具體狀態類的實例,這個具體狀態類的實例給出環境對象的現有實例。
狀態模式優缺點
優點:
1)?每個狀態都是一個子類,只要增加狀態就要增加子類,修改狀態,只修改一個子類即可。
2) 結構清晰,避免了過多的switch...case或者if...else語句的使用,避免了程序的復雜性,提高可維護性。
3) State對象可被共享 如果State對象沒有實例變量—即它們表示的狀態完全以它們的類型來編碼—那么各Context對象可以共享一個State對象。當狀態以這種方式被共享時, 它們必然是沒有內部狀態, 只有行為的輕量級對象。
缺點:
????1) 狀態模式的使用必然會增加系統類和對象的個數。
??? 2) 狀態模式的結構與實現都較為復雜,如果使用不當將導致程序結構和代碼的混亂。
狀態模式和策略模式比較
? ? ? ?在狀態模式中,狀態的變遷是由對象的內部條件決定,外界只需關心其接口,不必關心其狀態對象的創建和轉換。
?????? 而策略模式里,采取何種策略由外部條件(C)決定。Strategy模式與State模式的結構形式完全一樣。但它們的應用場景(目的)卻不一樣,State模式重在強調對象的內部狀態的變化改變對象的行為,Strategy模式重在外部對策略的選擇,策略的選擇由外部條件決定,也就是說算法動態的切換。但由它們的結構是如此的相似。我們可以認為狀態模式是完全封裝且自修改的策略模式。
? ? ? ?所以說策略和狀態模式是孿生兄弟。
狀態模式的適用性
1)??一個對象的行為取決于它的狀態, 并且它必須在運行時刻根據狀態改變它的行為。
2)??代碼中包含大量與對象狀態有關的條件語句:一個操作中含有龐大的多分支的條件(if else(或switch case)語句,且這些分支依賴于該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常 , 有多個操作包含這一相同的條件結構。 State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作為一個對象,這一對象可以不依賴于其他對象而獨立變化。
JDK中用到的狀態模式
java.util.Iterator?
迭代器模式的角色組成
1) 迭代器角色(Iterator):迭代器角色負責定義訪問和遍歷元素的接口。
2) 具體迭代器角色(Concrete Iterator):具體迭代器角色要實現迭代器接口,并要記錄遍歷中的當前位置。
3) 容器角色(Container):容器角色負責提供創建具體迭代器角色的接口。
4) 具體容器角色(Concrete Container):具體容器角色實現創建具體迭代器角色的接口—這個具體迭代器角色與該容器的結構相關。
javax.faces.lifecycle.LifeCycle#execute()
(FacesServlet由此控制,行為取決于JSF生命周期的當前階段(狀態))
代碼實例
這個是錯誤示例喲,大家有沒有這么判斷過呢?
public class Order {public static void main(String [] args) {// 關于訂單狀態的事情,大家有沒有這樣判斷過String stateName = getStateName(1);System.out.println(stateName);}/*** @method getStateName* @description 獲取訂單狀態的方法* 訂單狀態1、已下單2、已付款3、已發貨4、送貨中5、確認收貨* @date: 2018/12/19 22:04* @author: Ni Shichao* @param status 狀態* @return*/public static String getStateName (int status) {String stateName = "" ;if (status == 1) {stateName = "已下單";} else if (status == 2) {stateName = "已付款";} else if (status == 3) {stateName = "已發貨";} else if (status == 4) {stateName = "送貨中";} else if (status == 5) {stateName = "確認收貨";}return stateName;} }接下來是狀態模式的使用
State接口
public interface State {void handle(); }定義一個環境類來維護State接口?
public class Context {private State state;public Context() {}public Context(State state) {this.state = state;}public void setState(State state) {System.out.println("訂單信息已更新!");this.state = state;this.state.handle();}?具體狀態角色??ConcreteState
public class Booked implements State {@Overridepublic void handle() {System.out.println("您已下單!");} }其余狀態角色類是一樣的,我就不復制啦。
測試類
public class Client {public static void main(String [] args) {Context context = new Context();context.setState(new Booked());context.setState(new Payed());context.setState(new Sended());context.setState(new InWay());context.setState(new Recieved());} }測試結果:
訂單信息已更新! 您已下單! 訂單信息已更新! 您已付款! 訂單信息已更新! 已發貨! 訂單信息已更新! 送貨中。。。 訂單信息已更新! 已確認收貨!總結
狀態模式的主要優點在于封裝了轉換規則,并枚舉可能的狀態,它將所有與某個狀態有關的行為放到一個類中,并且可以方便地增加新的狀態,只需要改變對象狀態即可改變對象的行為,還可以讓多個環境對象共享一個狀態對象,從而減少系統中對象的個數;其缺點在于使用狀態模式會增加系統類和對象的個數,且狀態模式的結構與實現都較為復雜,如果使用不當將導致程序結構和代碼的混亂,對于可以切換狀態的狀態模式不滿足“開閉原則”的要求。
總結了一下設計模式之狀態模式,希望能幫助到大家。
總結
以上是生活随笔為你收集整理的设计模式之状态模式(State)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 垃圾回收题目_Java垃圾收集
- 下一篇: n1 linux 进不了桌面,[N1盒子