設計模式之狀態模式(State)

gamebus發表於2021-09-09

概述

狀態模式中的行為是由狀態決定的,不同的狀態有不同的行為,狀態模式把物件的行為包裝在不同的具體狀態物件裡,每一個狀態物件都有一個共同的抽象狀態基類。狀態模式的意圖是讓一個物件在其內部狀態改變的時候,其行為也隨之改變。

定義:當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了基類。

使用場景
  • 當一個物件的行為取決於它的狀態,並且它必須在執行時根據狀態改變它的行為。

  • 程式碼中含有大量與物件狀態有關的條件語句,例如。一個操作中含有龐大的多分支語句(if—else或者switch-case語句),且這些分支依賴於該物件的狀態。

UML

圖片描述

狀態模式UML

簡單實現

Context:環境類,定義客戶感興趣的介面,透過多型維護一個State子類的例項,這個例項定義了物件的當前狀態。

package com.dsguo.state;public class Context {    //維護一個State的例項
    private State state;    public Context(State state) {        this.state = state;
    }    //設定狀態
    public void setState(State state) {        this.state = state;
    }    //具體行為
    public void dosomething() {
        state.dosomething();
    }
}

State:抽象狀態,可以是抽象類也可以是介面,表示狀態下的行為。

package com.dsguo.state;public interface State {    void dosomething();
}

ConcreteStateA,ConcreteStateB:具體實現類,每一個具體的狀態類實現抽象State中定義的介面,從而達到不同狀態的不同行為。

package com.dsguo.state;public class ConcreteStateA implements State {    @Override
    public void dosomething() {
        System.out.println("現在狀態為A,做一些事情");
    }
}
package com.dsguo.state;public class ConcreteStateB implements State {    @Override
    public void dosomething() {
        System.out.println("現在狀態為B,做另外一些事情");
    }
}

最後看客戶端Client.java

package com.dsguo.state;public class Client {    public static void main(String[] args) {        //透過構造方法傳入狀態A
        Context context = new Context(new ConcreteStateA());
        context.dosomething();        //設定狀態B
        context.setState(new ConcreteStateB());
        context.dosomething();
    }
}

執行結果:
現在狀態為A,做一些事情
現在狀態為B,做另外一些事情

總結

狀態模式的關鍵點在於不同狀態下對於同一行為的有不同的響應,這其實就是if-else或者switch-case,但是如果用if-else或者switch-case使得邏輯都耦合在一起,易於出錯,透過狀態模式可以很好的消除這種“醜陋”的邏輯處理。當然並不是說if-else就一無是處,具體的使用還要看具體的使用場景。符合場景可以使用狀態模式。

優點:State模式將所有與一個特定的狀態相關的行為都放入一個狀態物件中,它提供了一個更好的方法來組織與特定的狀態相關的程式碼,將繁瑣的狀態判斷裝換成結構清晰的狀態類族,在避免程式碼膨脹的同時也保證了可擴充套件性和可維護性。

缺點:增加系統類的物件的個數



作者:ikonan
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4687/viewspace-2816020/,如需轉載,請註明出處,否則將追究法律責任。

相關文章