java設計模式之狀態模式

狀態模式的定義:

  狀態模式也叫做狀態機模式,運行對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類,屬於行爲型設計模式。算法

  狀態模式中類的行爲是由狀態決定的,在不一樣的狀態下有不一樣的行爲。其意圖是讓一個對象在其內部改變的時候,行爲也隨之改變。設計模式

狀態模式的核心是裝態與行爲綁定,不一樣的狀態對應不一樣的行爲。架構

狀態模式的應用場景:

  • 行爲隨狀態改變而改變的場景。
  • 一個操做中含有龐大的多分支結構,而且這些分支取決於對象的狀態。

狀態模式的UML類圖:

  狀態模式的UML類圖就不畫了,由於它和策略模式的UML類圖基本一致,它們都包含三個角色,ide

其中環境類角色(Context)分別是負責切換策略和狀態,抽象角色分別是定義不一樣策略和不一樣狀態測試

的行爲,具體角色分別是策略的具體實現和狀態的具體實現,惟一的區別是狀態模式在完成某個狀態this

的行爲以後還有可能會切換到其餘狀態。spa

使用狀態模式實現登陸狀態自由切換:

  當咱們瀏覽博客園的文章時,若是咱們以爲文章很好,忍不住想評論、收藏。可是若是咱們處於未登陸的狀態,就會自動跳轉到登陸頁面設計

這裏涉及到的狀態有兩種登陸和未登陸,行爲有評論和收藏。下面使用狀態模式來實現這個邏輯,代碼以下。code

首先建立抽象狀態角色類,定義評論和收藏兩個行爲對象

public abstract class UserState {
    protected AppContext context;

    public void setContext(AppContext context) {
        this.context = context;
    }

    public abstract void favorite();

    public abstract void comment(String comment);
}

而後建立未登陸狀態類,定義在未登陸狀態下,兩種行爲的具體實現

public class UnLoginState extends UserState {

    @Override
    public void favorite() {
        this.switch2login();
        this.context.getState().favorite();
    }

    @Override
    public void comment(String comment) {
        this.switch2login();
        this.context.getState().comment(comment);
    }

    private void switch2login(){
        System.out.println("跳轉到登陸頁!");
        this.context.setState(this.context.STATE_LOGIN);
    }
}

建立登陸狀態類,定義在登陸狀態下,兩種行爲的具體實現

public class LoginState extends UserState {
    @Override
    public void favorite() {
        System.out.println("收藏成功!");
    }

    @Override
    public void comment(String comment) {
        System.out.println(comment);
    }
}

建立上下文角色類,根據登陸狀態切換具體的行爲

public class AppContext {

    public static final UserState STATE_LOGIN = new LoginState();
    public static final UserState STATE_UNLOGIN = new UnLoginState();

    private UserState currentState = STATE_UNLOGIN;

    {
        STATE_LOGIN.setContext(this);
        STATE_UNLOGIN.setContext(this);
    }

    public void setState(UserState state){
        this.currentState = state;
    }

    public UserState getState(){
        return this.currentState;
    }

    public void favorite(){
        this.currentState.favorite();
    }

    public void comment(String comment){
        this.currentState.comment(comment);
    }
}

最後編寫客戶端測試代碼。

public class Test {
    public static void main(String[] args) {
        AppContext context = new AppContext();
        context.favorite();
        context.comment("評論:好文章,360個贊");
    }
}

狀態模式和責任鏈模式的區別:

  • 狀態模式和責任鏈模式都能消除if...else分支過多的問題。可是在某些狀況下,狀態模式中的狀態能夠理解爲責任,那麼這種狀況下,兩種模式均可以使用。
  • 從定義上來看,狀態模式強調的是一個對象內在狀態的改變,而責任鏈模式強調的是外部節點對象間的改變。
  • 從代碼實現上來看,二者最大的區別就是狀態模式的各個狀態對象知道本身要進入的下一個狀態對象,而責任鏈模式並不清楚其下一個節點處理對象,由於鏈式組裝由客戶端負責。

狀態模式和策略模式的區別:

  狀態模式和策略模式的UML類圖架構幾乎徹底同樣,但二者的應用場景是不同的。策略模式的多種算法行爲則其一都能知足,彼此之間是獨立的,用戶可自行更換策略算法;而

狀態模式的各個狀態之間存在相互關係,彼此之間必定的條件下存在自動切換的效果,而且用戶沒法指定狀態,只能設置初始狀態,由於狀態是根據行爲而改變的。

狀態模式的優勢:

  • 結構清晰:將狀態獨立爲類,清楚了冗餘的if...else或switch...case語句,使代碼更加間接,提升了系統的可維護性。
  • 將狀態轉換現實化:一般對象內部都是使用數值類型來定義狀態的,狀態的切換經過賦值進行表現,不夠直觀;而使用狀態類,當切換狀態時,是以不一樣的類進行表示的,轉換目的更加明確。
  • 狀態類職責明確且具有擴展性。

狀態模式的缺點:

  • 類膨脹,若是一個類的狀態過多,則會形成狀態類過多。
  • 狀態模式的結構和實現都較爲複雜,若是使用不當,將致使程序結構和代碼的混亂。
  • 狀態模式對開閉原則的支持不太友好,若是新增了狀態類,則須要修改負責切換到該類的狀態類。並且修改某個狀態的行爲也要修改源碼。
相關文章
相關標籤/搜索