状态模式浅谈

135 阅读2分钟

「这是我参与2022首次更文挑战的第40天,活动详情查看:2022首次更文挑战」。

一、什么是状态模式

状态模式:对于有状态的对象,把不同的状态的判断逻辑提取到不同的状态对象中,允许状态对象在对象状态发生变化时改变其状态。比如有开始,审核中,审核通过几个状态,可以通过建立几个状态对象,出现状态变更时调用相应的状态对象。我们日常生活中常见的红绿灯,洗衣机这些,都有其相应的状态转换。

二、状态模式的实现

public class Context {
    private AbstractState state;

    public Context() {
        this.state = new RedLightState();
    }

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

    public AbstractState getState() {
        return this.state;
    }

    public void redToGreen() {
        state.doNextAction(this);
    }

    public void GreenToYellow() {
        state.doNextAction(this);
    }

    public void YellowToRed() {
        state.doNextAction(this);
    }
}

环境类角色,持有状态类,保持当前状态。

public abstract class AbstractState {
    protected String lightColor;

    public void setLightColor(String lightColor) {
        this.lightColor = lightColor;
    }

    public abstract void doNextAction(Context context);
}

抽象状态角色

public class RedLightState extends AbstractState {
    public RedLightState() {
        super.lightColor = "Red";
        System.out.println("当前为Red");
    }

    @Override
    public void doNextAction(Context context) {
        String lightColor = context.getState().lightColor;
        System.out.println(lightColor + "变为Green");
        if ("Red".equals(lightColor)) {
            context.setState(new GreenLightState());
        } else {
            System.out.println("灯的颜色转换不正确");
        }
    }
}

具体状态类,当前为红灯,此状态相关的操作是切换为绿灯。

public class GreenLightState extends AbstractState {
    public GreenLightState() {
        super.lightColor = "Green";
        System.out.println("当前为Green");
    }

    @Override
    public void doNextAction(Context context) {
        String lightColor = context.getState().lightColor;
        System.out.println(lightColor + "变为Yellow");
        if ("Green".equals(lightColor)) {
            context.setState(new YellowLightState());
        } else {
            System.out.println("灯的颜色转换不正确");
        }
    }
}

具体状态类,当前为绿灯,相关操作为切换为黄灯

public class YellowLightState extends AbstractState {
    public YellowLightState() {
        super.lightColor = "Yellow";
        System.out.println("当前为Yellow");
    }

    @Override
    public void doNextAction(Context context) {
        String lightColor = context.getState().lightColor;
        System.out.println(lightColor + "变为Red");
        if ("Yellow".equals(lightColor)) {
            context.setState(new RedLightState());
        } else {
            System.out.println("灯的颜色转换不正确");
        }
    }
}

具体状态类,当前为黄灯,相关操作为切换为红灯。

public class StateTest {
    public static void main(String[] args) {
        Context context = new Context();
        context.redToGreen();
        context.GreenToYellow();
        context.YellowToRed();
    }
}

通过调用环境中的变换状态的方法,可以方便的完成状态的切换。 image.png

三、总结

优点:可以将复杂的if else判断简化为多个状态对象,使得代码结构清晰,状态对象满足单一职责原则。可以方便的扩展新的状态,只需要新增相应状态的子类。

缺点:状态如果越多,状态对象也会相应增多,状态模式的结构较为复杂,相比if else,使用不当会造成代码混乱。

状态模式角色:

  1. 环境类:内部维持一个状态,负责具体状态的切换。
  2. 抽象状态类:定义了一个接口,这个接口的作用是在状态切换时,执行与此状态相关的操作,比如红绿灯中的切换灯光的颜色。
  3. 具体状态角色:实现了抽象状态类,比如红灯态,实现了抽象状态类中的方法,切换灯光颜色为红色。