日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

状态模式(State模式)

發(fā)布時間:2023/12/20 编程问答 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 状态模式(State模式) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在軟件開發(fā)過程中,應(yīng)用程序中的部分對象可能會根據(jù)不同的情況做出不同的行為,我們把這種對象稱為有狀態(tài)的對象,而把影響對象行為的一個或多個動態(tài)變化的屬性稱為狀態(tài)。當(dāng)有狀態(tài)的對象與外部事件產(chǎn)生互動時,其內(nèi)部狀態(tài)就會發(fā)生改變,從而使其行為也發(fā)生改變。如人都有高興和傷心的時候,不同的情緒有不同的行為,當(dāng)然外界也會影響其情緒變化。

對這種有狀態(tài)的對象編程,傳統(tǒng)的解決方案是:將這些所有可能發(fā)生的情況全都考慮到,然后使用 if-else 或 switch-case 語句來做狀態(tài)判斷,再進(jìn)行不同情況的處理。但是顯然這種做法對復(fù)雜的狀態(tài)判斷存在天然弊端,條件判斷語句會過于臃腫,可讀性差,且不具備擴(kuò)展性,維護(hù)難度也大。且增加新的狀態(tài)時要添加新的 if-else 語句,這違背了“開閉原則”,不利于程序的擴(kuò)展。

以上問題如果采用“狀態(tài)模式”就能很好地得到解決。狀態(tài)模式的解決思想是:當(dāng)控制一個對象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過于復(fù)雜時,把相關(guān)“判斷邏輯”提取出來,用各個不同的類進(jìn)行表示,系統(tǒng)處于哪種情況,直接使用相應(yīng)的狀態(tài)類對象進(jìn)行處理,這樣能把原來復(fù)雜的邏輯判斷簡單化,消除了 if-else、switch-case 等冗余語句,代碼更有層次性,并且具備良好的擴(kuò)展力。

狀態(tài)模式的定義與特點(diǎn)

狀態(tài)(State)模式的定義:對有狀態(tài)的對象,把復(fù)雜的“判斷邏輯”提取到不同的狀態(tài)對象中,允許狀態(tài)對象在其內(nèi)部狀態(tài)發(fā)生改變時改變其行為。

狀態(tài)模式是一種對象行為型模式,其主要優(yōu)點(diǎn)如下。

  • 結(jié)構(gòu)清晰,狀態(tài)模式將與特定狀態(tài)相關(guān)的行為局部化到一個狀態(tài)中,并且將不同狀態(tài)的行為分割開來,滿足“單一職責(zé)原則”。
  • 將狀態(tài)轉(zhuǎn)換顯示化,減少對象間的相互依賴。將不同的狀態(tài)引入獨(dú)立的對象中會使得狀態(tài)轉(zhuǎn)換變得更加明確,且減少對象間的相互依賴。
  • 狀態(tài)類職責(zé)明確,有利于程序的擴(kuò)展。通過定義新的子類很容易地增加新的狀態(tài)和轉(zhuǎn)換。

  • 狀態(tài)模式的主要缺點(diǎn)如下。

  • 狀態(tài)模式的使用必然會增加系統(tǒng)的類與對象的個數(shù)。
  • 狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)會導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。
  • 狀態(tài)模式對開閉原則的支持并不太好,對于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源碼,否則無法切換到新增狀態(tài),而且修改某個狀態(tài)類的行為也需要修改對應(yīng)類的源碼。
  • 狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)

    狀態(tài)模式把受環(huán)境改變的對象行為包裝在不同的狀態(tài)對象里,其意圖是讓一個對象在其內(nèi)部狀態(tài)改變的時候,其行為也隨之改變。現(xiàn)在我們來分析其基本結(jié)構(gòu)和實(shí)現(xiàn)方法。

    1. 模式的結(jié)構(gòu)

    狀態(tài)模式包含以下主要角色。

  • 環(huán)境類(Context)角色:也稱為上下文,它定義了客戶端需要的接口,內(nèi)部維護(hù)一個當(dāng)前狀態(tài),并負(fù)責(zé)具體狀態(tài)的切換。
  • 抽象狀態(tài)(State)角色:定義一個接口,用以封裝環(huán)境對象中的特定狀態(tài)所對應(yīng)的行為,可以有一個或多個行為。
  • 具體狀態(tài)(Concrete State)角色:實(shí)現(xiàn)抽象狀態(tài)所對應(yīng)的行為,并且在需要的情況下進(jìn)行狀態(tài)切換。

  • 其結(jié)構(gòu)圖如圖 1 所示。


    圖1 狀態(tài)模式的結(jié)構(gòu)圖

    2. 模式的實(shí)現(xiàn)

    狀態(tài)模式的實(shí)現(xiàn)代碼如下:

    public class StatePatternClient {public static void main(String[] args) {Context context = new Context(); //創(chuàng)建環(huán)境context.Handle(); //處理請求context.Handle();context.Handle();context.Handle();} }//環(huán)境類 class Context {private State state;//定義環(huán)境類的初始狀態(tài)public Context() {this.state = new ConcreteStateA();}//設(shè)置新狀態(tài)public void setState(State state) {this.state = state;}//讀取狀態(tài)public State getState() {return (state);}//對請求做處理public void Handle() {state.Handle(this);} }//抽象狀態(tài)類 abstract class State {public abstract void Handle(Context context); }//具體狀態(tài)A類 class ConcreteStateA extends State {public void Handle(Context context) {System.out.println("當(dāng)前狀態(tài)是 A.");context.setState(new ConcreteStateB());} }//具體狀態(tài)B類 class ConcreteStateB extends State {public void Handle(Context context) {System.out.println("當(dāng)前狀態(tài)是 B.");context.setState(new ConcreteStateA());} }

    程序運(yùn)行結(jié)果如下:

    當(dāng)前狀態(tài)是 A. 當(dāng)前狀態(tài)是 B. 當(dāng)前狀態(tài)是 A. 當(dāng)前狀態(tài)是 B.

    狀態(tài)模式的應(yīng)用場景

    通常在以下情況下可以考慮使用狀態(tài)模式。

    • 當(dāng)一個對象的行為取決于它的狀態(tài),并且它必須在運(yùn)行時根據(jù)狀態(tài)改變它的行為時,就可以考慮使用狀態(tài)模式。
    • 一個操作中含有龐大的分支結(jié)構(gòu),并且這些分支決定于對象的狀態(tài)時。

    狀態(tài)模式的擴(kuò)展

    在有些情況下,可能有多個環(huán)境對象需要共享一組狀態(tài),這時需要引入享元模式,將這些具體狀態(tài)對象放在集合中供程序共享,其結(jié)構(gòu)圖如圖 5 所示。
    ?


    圖5 共享狀態(tài)模式的結(jié)構(gòu)圖


    分析:共享狀態(tài)模式的不同之處是在環(huán)境類中增加了一個 HashMap 來保存相關(guān)狀態(tài),當(dāng)需要某種狀態(tài)時可以從中獲取,其程序代碼如下:

    package state;import java.util.HashMap;public class FlyweightStatePattern {public static void main(String[] args) {ShareContext context = new ShareContext(); //創(chuàng)建環(huán)境context.Handle(); //處理請求context.Handle();context.Handle();context.Handle();} }//環(huán)境類 class ShareContext {private ShareState state;private HashMap<String, ShareState> stateSet = new HashMap<String, ShareState>();public ShareContext() {state = new ConcreteState1();stateSet.put("1", state);state = new ConcreteState2();stateSet.put("2", state);state = getState("1");}//設(shè)置新狀態(tài)public void setState(ShareState state) {this.state = state;}//讀取狀態(tài)public ShareState getState(String key) {ShareState s = (ShareState) stateSet.get(key);return s;}//對請求做處理public void Handle() {state.Handle(this);} }//抽象狀態(tài)類 abstract class ShareState {public abstract void Handle(ShareContext context); }//具體狀態(tài)1類 class ConcreteState1 extends ShareState {public void Handle(ShareContext context) {System.out.println("當(dāng)前狀態(tài)是: 狀態(tài)1");context.setState(context.getState("2"));} }//具體狀態(tài)2類 class ConcreteState2 extends ShareState {public void Handle(ShareContext context) {System.out.println("當(dāng)前狀態(tài)是: 狀態(tài)2");context.setState(context.getState("1"));} }

    程序運(yùn)行結(jié)果如下:

    當(dāng)前狀態(tài)是: 狀態(tài)1 當(dāng)前狀態(tài)是: 狀態(tài)2 當(dāng)前狀態(tài)是: 狀態(tài)1 當(dāng)前狀態(tài)是: 狀態(tài)2

    拓展

    狀態(tài)模式與責(zé)任鏈模式的區(qū)別

    狀態(tài)模式和責(zé)任鏈模式都能消除 if-else 分支過多的問題。但在某些情況下,狀態(tài)模式中的狀態(tài)可以理解為責(zé)任,那么在這種情況下,兩種模式都可以使用。

    從定義來看,狀態(tài)模式強(qiáng)調(diào)的是一個對象內(nèi)在狀態(tài)的改變,而責(zé)任鏈模式強(qiáng)調(diào)的是外部節(jié)點(diǎn)對象間的改變。

    從代碼實(shí)現(xiàn)上來看,兩者最大的區(qū)別就是狀態(tài)模式的各個狀態(tài)對象知道自己要進(jìn)入的下一個狀態(tài)對象,而責(zé)任鏈模式并不清楚其下一個節(jié)點(diǎn)處理對象,因?yàn)殒準(zhǔn)浇M裝由客戶端負(fù)責(zé)。

    狀態(tài)模式與策略模式的區(qū)別

    狀態(tài)模式和策略模式的 UML 類圖架構(gòu)幾乎完全一樣,但兩者的應(yīng)用場景是不一樣的。策略模式的多種算法行為擇其一都能滿足,彼此之間是獨(dú)立的,用戶可自行更換策略算法,而狀態(tài)模式的各個狀態(tài)間存在相互關(guān)系,彼此之間在一定條件下存在自動切換狀態(tài)的效果,并且用戶無法指定狀態(tài),只能設(shè)置初始狀態(tài)。

    進(jìn)階閱讀

    如果您想深入了解狀態(tài)模式,可猛擊閱讀以下文章。

    • 《使用狀態(tài)模式自由切換登錄狀態(tài)》
    • 《使用狀態(tài)機(jī)實(shí)現(xiàn)訂單狀態(tài)流轉(zhuǎn)控制》
    • 《狀態(tài)模式在JSF源碼中的應(yīng)用》

    總結(jié)

    以上是生活随笔為你收集整理的状态模式(State模式)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。