1.18(设计模式)状态模式

状态模式:当对象状态改变时行为也随之改变,看起来就像是这个类发生了改变。

首先对象有状态,行为由状态决定。

假设现在有一个游戏角色,有正常状态、加速状态、减速状态、眩晕状态。

游戏角色不同状态下的行为是不同的,减速跑的慢一些、眩晕不能跑。

我们将游戏角色转换为代码,先看不使用状态模式的情况。

游戏角色类

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();
    }
}
运行结果:
正常状态
加速状态
眩晕状态
减速状态
扫描二维码关注公众号,回复: 6547611 查看本文章

游戏角色中有状态,执行run方法时会根据状态打印出不用的结果,即对象状态的改变也会造成行为的改变。

这样实现也可以,但如果后续分支状态过多,需要大量的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

猜你喜欢

转载自www.cnblogs.com/huang-changfan/p/11050621.html