狀態模式的簡單使用

前言

狀態模式簡而言之就是指我要做一件事,這件事能導致什麼後果我不管,由當前狀態來決定,比如我有兩塊錢,我想吃點東西就去了商店,結果怎麼樣得看這個商店有兩塊錢的什麼東西,如果商品都大於兩塊,我還不能吃到食物了;這就和策略模式特別像了,他們的結構完全一樣,狀態模式的行爲是由狀態來決定,行爲是平行的不可替換的,而策略模式的行爲是可替換的,因爲它都是爲了完成同一個行爲。

適用情況

1,一個對象的行爲取決於它的狀態,而且程序執行中必須改變其行爲。
2,程序中有很多同一執行入口的if-else語句。

類與角色

Context: 定義統一執行入口,維護行爲的具體實例,或者說就是一個狀態行爲管理器。
State: 抽象狀態接口,定義抽象行爲接口。
ConcreteState: 抽象接口具體實現類,多個狀態對應多個接口實現類,滿足不同的行爲。

Demo

寫一個Demo,描述一個購物車頁面的場景,用戶可以刪除商品和結算商品,但是刪除和結算的行爲和用戶是否登錄有關係,如果沒有登錄就去登錄,如果已經登錄了,那就執行相關操作。

定義抽象狀態接口State,抽象刪除商品和結算方法:

package com.demo.state;

import android.content.Context;

/**
 * Created by italkbb on 2017/12/18.
 */

public interface UserState {
    /**
     * 刪除商品
     */
    void delShop(Context context);

    /**
     * 結算
     */
    void settlement(Context context);
}

實現具體狀態接口:

package com.demo.state;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * Created by italkbb on 2017/12/18.
 */

public class LoginedState implements UserState {
    public final static String CLASSNAME = LoginedState.class.getSimpleName();

    @Override
    public void delShop(Context context) {
        Log.e(CLASSNAME,"刪除購物車商品");
    }

    @Override
    public void settlement(Context context) {
        // 登錄了直接去支付頁面
        Intent intent = new Intent(context,PayActivity.class);
        context.startActivity(intent);
    }
}
package com.demo.state;

import android.content.Context;
import android.content.Intent;

/**
 * Created by italkbb on 2017/12/18.
 */

public class LogoutState implements UserState {
    @Override
    public void delShop(Context context) {
        Intent intent = new Intent(context,LoginActivity.class);
        context.startActivity(intent);
    }

    @Override
    public void settlement(Context context) {
        Intent intent = new Intent(context,LoginActivity.class);
        context.startActivity(intent);
    }
}

定義一個UserManager管理類,統一調用接口:

package com.demo.state;

import android.content.Context;

/**
 * Created by italkbb on 2017/12/18.
 */

public class UserManager {
    // 默認未登錄
    private UserState mState = new LogoutState();

    private static UserManager mUserManager = new UserManager();

    private UserManager(){

    }

    /**
     * 對外公佈獲取管理類接口
     * @return
     */
    public static UserManager getUserManager(){
        return mUserManager;
    }

    public void setState(UserState userState){
        this.mState = userState;
    }

    /**
     * 統一刪除接口
     * @param context
     */
    public void delShop(Context context){
        mState.delShop(context);
    }

    /**
     * 統一結算接口
     * @param context
     */
    public void settlement(Context context){
        mState.settlement(context);
    }


}

簡單示例一下使用:

package com.demo.state;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import teltplay.example.com.kotlindemo.R;

public class CartActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cart);
//        // 在登錄成功後
//        UserManager.getUserManager().setState(new LoginedState());
//        // 在登出後
//        UserManager.getUserManager().setState(new LogoutState());

        findViewById(R.id.btn_cart).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                UserManager.getUserManager().settlement(CartActivity.this);
            }
        });

        findViewById(R.id.btn_del).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                UserManager.getUserManager().settlement(CartActivity.this);
            }
        });
    }
}

後記

最後簡單的說一下狀態模式的優缺點,優點是減少了if-else判斷,讓結構很清晰,而且調用的時候不用去管行爲結果,只需要調用統一管理類提供的公用方法。這樣避免了代碼的冗餘,也同樣提高了代碼的可擴展性和可維護性;缺點還是如策略模式,狀態越多類的數量就會增加,但這一般情況下又算什麼缺點呢。

發佈了39 篇原創文章 · 獲贊 20 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章