1.18(設計模式)狀態模式

狀態模式:當對象狀態改變時行爲也隨之改變,看起來就像是這個類發生了改變。html

首先對象有狀態,行爲由狀態決定。ide

 

假設如今有一個遊戲角色,有正常狀態、加速狀態、減速狀態、眩暈狀態。this

遊戲角色不一樣狀態下的行爲是不一樣的,減速跑的慢一些、眩暈不能跑。spa

咱們將遊戲角色轉換爲代碼,先看不使用狀態模式的狀況。code

 

遊戲角色類htm

public class Hero {
public static final int COMMON = 1;//正常狀態
    
    public static final int SPEED_UP = 2;//加速狀態
    
    public static final int SPEED_DOWN = 3;//減速狀態
    
    public static final int SWIM = 4;//眩暈狀態
    
    private int state = COMMON;//默認是正常狀態

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }
    
    public void run() {
        if(state == COMMON) {
            System.out.println("正常狀態");
        }else if(state == SPEED_UP) {
            System.out.println("加速狀態");
        }
        else if(state == SPEED_DOWN) {
            System.out.println("減速狀態");
        }
        else if(state == SWIM) {
            System.out.println("眩暈狀態");
        }
    }
}

 

Main對象

public class Main {
    public static void main(String[] args) {
        //默認正常狀態
        Hero hcf = new Hero();
        hcf.run();
        //加速狀態
        hcf.setState(Hero.SPEED_UP);
        hcf.run();
        //眩暈狀態
        hcf.setState(Hero.SWIM);
        hcf.run();
        //減速狀態
        hcf.setState(Hero.SPEED_DOWN);
        hcf.run();
    }
}
運行結果:
正常狀態
加速狀態
眩暈狀態
減速狀態

 

遊戲角色中有狀態,執行run方法時會根據狀態打印出不用的結果,即對象狀態的改變也會形成行爲的改變。blog

這樣實現也能夠,但若是後續分支狀態過多,須要大量的if else,並且Hero的狀態只對象Hero有效,怪獸一樣有這些狀態,接口

這些狀態沒法複用。遊戲

 

 

這時咱們就能夠採用狀態模式

首先須要將狀態抽取出來,每個狀態對應一個狀態類

 

狀態接口

public interface State {
    public void change(Hero hero);
}

 

加速狀態

public class SpeedUpState implements State {

    @Override
    public void change(Hero hero) {//傳遞英雄對象,改變英雄對象的狀態
        // TODO Auto-generated method stub
        hero.setState(this);
    }

    @Override
    public String toString() {
        return "加速狀態";
    }
    
    
}

 

減速狀態

public class SpeedDownState implements State {

    @Override
    public void change(Hero hero) {//傳遞英雄對象,改變英雄對象的狀態
        // TODO Auto-generated method stub
        hero.setState(this);
    }

    @Override
    public String toString() {
        return "減速狀態";
    }
    
    
}

 

眩暈狀態

public class SwimState implements State{
    @Override
    public void change(Hero hero) {//傳遞英雄對象,改變英雄對象的狀態
        // TODO Auto-generated method stub
        hero.setState(this);
    }

    @Override
    public String toString() {
        return "眩暈狀態";
    }
}

 

正常狀態

public class CommonState implements State{
    @Override
    public void change(Hero hero) {//傳遞英雄對象,改變英雄對象的狀態
        // TODO Auto-generated method stub
        hero.setState(this);
    }

    @Override
    public String toString() {
        return "正常狀態";
    }
}

 

 

每個狀態對應一個狀態類,當英雄狀態須要發送變化時,只需建立狀態類,而後將heroz做爲參數,調用狀態類的change方法。

change方法會將當前狀態對象設置到hero中的state屬性,後續直接獲取英雄狀態便可。

 

Main

public class Main {
    public static void main(String[] args) {
        Hero hcf = new Hero();
        //正常狀態
        CommonState commonState = new CommonState();
        commonState.change(hcf);
        System.out.println(hcf.getState().toString());
        
        //加速狀態
        SpeedUpState speedUpState = new SpeedUpState();
        speedUpState.change(hcf);
        System.out.println(hcf.getState().toString());

        //眩暈狀態
        SwimState swimState = new SwimState();
        swimState.change(hcf);
        System.out.println(hcf.getState().toString());

        //減速狀態
        SpeedDownState speedDownState = new SpeedDownState();
        speedDownState.change(hcf);
        System.out.println(hcf.getState().toString());

    }
}
運行結果:
正常狀態
加速狀態
眩暈狀態
減速狀態

 

後續還有新的狀態只需添加狀態類便可,並且能夠進一步抽象,使Heor類和怪獸類實現同一個接口,這樣這些狀態對於Hero和怪獸都適用。

 

 

參考資料:

https://www.runoob.com/design-pattern/state-pattern.html

https://www.cnblogs.com/zuoxiaolong/p/pattern22.html

相關文章
相關標籤/搜索