(行为型模式)状态模式

106 阅读3分钟

前言

状态模式它允许对象在其内部状态改变时改变其行为。这种模式被用来解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。

例如,在一个自动售货机中,一个咖啡机可能有多种不同的状态,如“空闲”、“准备”和“咖啡制作中”。每个状态都有不同的行为,例如,如果咖啡机处于“空闲”状态,则按下“准备”按钮将会使咖啡机进入“准备”状态;如果咖啡机处于“准备”状态,则按下“制作”按钮将会使咖啡机进入“咖啡制作中”状态。状态模式可以帮助我们管理咖啡机的状态转换和不同状态下的行为。

角色

  • 环境类(Context):定义客户感兴趣的接口,并且保留一个具体状态类的实例。这个实例定义当前状态,并且可以通过
  • 抽象状态类(State):定义一个接口,用于定义一个状态所必须的行为。
  • 具体状态类(Concrete State):实现抽象状态类的接口,定义一个状态的具体行为。

示例

抽象状态类

public interface State {
    /**
     * 投币
     */
    void insertCoin();

    /**
     * 按下按钮
     */
    void pressButton();

    /**
     * 发放咖啡
     */
    void dispense();
}

空闲状态

public class IdleState implements State{

    private CoffeeMachine machine;

    public IdleState(CoffeeMachine machine) {
        this.machine = machine;
    }

    @Override
    public void insertCoin() {
        System.out.println("硬币投入成功");
        machine.setState(machine.getButtonEnabledState());
    }

    @Override
    public void pressButton() {
        System.out.println("请先投币");
    }

    @Override
    public void dispense() {
        System.out.println("请按下按钮发放咖啡");
    }
}

按钮已启用状态

public class ButtonEnabledState implements State{

    private CoffeeMachine machine;

    public ButtonEnabledState(CoffeeMachine machine) {
        this.machine = machine;
    }


    @Override
    public void insertCoin() {
        System.out.println("硬币已经投入过,按钮现在是启用状态");
    }

    @Override
    public void pressButton() {
        System.out.println("按钮按下,咖啡制作中....");
        machine.setState(machine.getMakingCoffeeState());
    }

    @Override
    public void dispense() {
        System.out.println("请按下按钮发放咖啡");
    }
}

制作咖啡状态

public class MakingCoffeeState implements State{

    private CoffeeMachine machine;

    public MakingCoffeeState(CoffeeMachine machine) {
        this.machine = machine;
    }

    @Override
    public void insertCoin() {
        System.out.println("硬币已经投入过,按钮现在是启用状态");
    }

    @Override
    public void pressButton() {
        System.out.println("咖啡正在制作中,请等待");
    }

    @Override
    public void dispense() {
        System.out.println("咖啡制作完成");
        machine.setState(machine.getIdleState());
    }
}

环境类

public class CoffeeMachine {
    private State idleState;
    private State buttonEnabledState;
    private State makingCoffeeState;
    private State state;

    public CoffeeMachine() {
        idleState = new IdleState(this);
        buttonEnabledState = new ButtonEnabledState(this);
        makingCoffeeState = new MakingCoffeeState(this);
        state = idleState;
    }

    public State getIdleState() {
        return idleState;
    }

    public State getButtonEnabledState() {
        return buttonEnabledState;
    }

    public State getMakingCoffeeState() {
        return makingCoffeeState;
    }

    public State getState() {
        return state;
    }

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

    public void insertCoin() {
        state.insertCoin();
    }

    public void pressButton() {
        state.pressButton();
    }

    public void dispense() {
        state.dispense();
    }
}

使用

public class Demo {

    public static void main(String[] args) {
        CoffeeMachine machine = new CoffeeMachine();
        machine.insertCoin();
        machine.pressButton();
        machine.dispense();
    }
}

输出

cfxZkt6t3O.jpg

优缺点

优点

  • 状态模式可以让您通过改变对象的状态来控制它的行为,这样就可以将复杂的条件分支语句转换成状态对象的一系列方法调用。这样可以使代码更加清晰、结构更加清晰,并且更容易维护和扩展。
  • 状态模式可以将每个状态封装到一个独立的类中,这样可以让不同的状态有不同的实现,并且可以在不同的状态之间转换。这样可以避免使用复杂的条件分支语句来控制对象的行为。

缺点

  • 状态模式会增加系统的复杂度,因为它需要定义许多状态类来封装不同的行为。这会增加系统的开发和维护成本。
  • 状态模式也可能会导致系统结构不清晰,因为它需要在不同的状态之间来回切换,这可能会导致系统的结构变得混乱