1. 程式人生 > >設計模式 --- 狀態模式

設計模式 --- 狀態模式

1.定義

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

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

 

2.使用場景

1)一個物件的行為取決於它的狀態,並且它必須在執行時根據狀態改變它的行為。

2)程式碼中包含大量與物件狀態有關的條件語句,例如一個操作中含有龐大的多分支語句,且這些分支依賴於該物件的狀態。

 

3.簡單實現

將電視的狀態分為開機和關機狀態,在開機狀態下遙控器可以切換頻道,調整音量,此時重複按開機鍵是無效的;在關機狀態下,頻道切換、調解音量關機鍵都是無效的,只有按開機才會生效。

普通實現:

//遙控器
public class TVController {
    //開機狀態
    private final static int POWER_ON = 1;
    //關機狀態
    private final static int POWER_OFF = 2 ;
    //當前狀態
    private int state = POWER_OFF;

    //開機按鈕
    public void powerON(){
        if (state == POWER_OFF){
            System.out.println("開機了...");
        }
        state = POWER_ON;
    }

    //關機按鈕
    public void powerOFF(){
        if (state == POWER_ON){
            System.out.println("關機了...");
        }
        state = POWER_OFF;
    }

    //切換頻道
    public void changeChannel(){
        if (state == POWER_ON){
            System.out.println("頻道切換...");
        }else {
            System.out.println("Tips : 未開機");
        }
    }

    //調節音量
    public void turnVoice(){
        if (state == POWER_ON){
            System.out.println("音量調解...");
        }else {
            System.out.println("Tips : 未開機");
        }
    }

}

通過state欄位來儲存電視機的狀態,各個操作根據state欄位的狀態來判斷是否執行。隨著後期狀態或者功能增加,就要不斷維護if...else 語句,程式碼會變得重複切混亂。我們用狀態模式來改造它。

//定義電視功能介面
interface TvState{
    //切換頻道
    void changeChannal();
    //調節音量
    void turnVoice();
}

//關機狀態 所用功能都無效
class PowerOffState implements TvState{

    @Override
    public void changeChannal() {
        System.out.println("未開機...切換頻道無效");
    }

    @Override
    public void turnVoice() {
        System.out.println("未開機...調解音量無效");
    }
}

//開機狀態
class PowerOnState implements TvState{

    @Override
    public void changeChannal() {
        System.out.println("頻道切換...");
    }

    @Override
    public void turnVoice() {
        System.out.println("音量調節...");
    }
}

//狀態介面
interface PowerController{
    //開機狀態
    void powerOn();
    //關機狀態
    void powerOff();
}

//遙控器
class TvContorller implements PowerController{

    TvState tvState;

    public void setTvState(TvState state){
        this.tvState = state;
    }

    @Override
    public void powerOn() {
        setTvState(new PowerOnState());
        System.out.println("開機...");
    }

    @Override
    public void powerOff() {
        setTvState(new PowerOffState());
        System.out.println("關機...");
    }

    //切換頻道
    public void changeChannal(){
        tvState.changeChannal();
    }

    public void turnVoice(){
        tvState.turnVoice();
    }

}

public class StateMode {

    public static void main(String[] arg){
        TvContorller tvContorller = new TvContorller();
        //設定開機狀態
        tvContorller.powerOn();
        tvContorller.changeChannal();
        tvContorller.turnVoice();
        //設定關機狀態
        tvContorller.powerOff();
        //已關機 無法切換頻道
        tvContorller.changeChannal();
    }

}

輸出:

 

4.小結

優點:

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

缺點:

會增加系統類和物件的個數。