设计模式-状态模式 State-一、简介概述

时间:2024-02-17 19:59:39

状态模式并不是很常用,但是在能够用到的场景里,它可以发挥很大的作用。

状态设计模式是一种行为型设计模式,它允许对象在其内部状态发生变化时改变其行为。这种模式可以消除大量的条件语句,并将每个状态的行为封装到单独的类中。

状态模式的主要组成部分如下:

  1. 上下文(Context):上下文通常包含一个具体状态的引用,用于维护当前状态。上下文委托给当前状态对象处理状态相关行为。
  2. 抽象状态(State):定义一个接口,用于封装与上下文的特定状态相关的行为。
  3. 具体状态(Concrete State):实现抽象状态接口,为具体状态定义行为。每个具体状态类对应一个状态。

现在来看一个简单的 Java 示例。假设要模拟一个简易的电视遥控器,具有开启、关闭和调整音量的功能。

如果不使用设计模式,编写出来的代码可能是这个样子的,我们需要针对电视机当前的状态为每一次操作编写判断逻辑:

public class TV {
    private boolean isOn;
    private int volume;

    public TV() {
        isOn = false;
        volume = 0;
    }

    public void turnOn() {
        // 如果是开启状态
        if (isOn) {
            System.out.println("TV is already on.");
            // 否则打开电视
        } else {
            isOn = true;
            System.out.println("Turning on the TV.");
        }
    }

    public void turnOff() {
        if (isOn) {
            isOn = false;
            System.out.println("Turning off the TV.");
        } else {
            System.out.println("TV is already off.");
        }
    }

    public void adjustVolume(int volume) {
        if (isOn) {
            this.volume = volume;
            System.out.println("Adjusting volume to: " + volume);
        } else {
            System.out.println("Cannot adjust volume, TV is off.");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        TV tv = new TV();

        tv.turnOn();
        tv.adjustVolume(10);
        tv.turnOff();
    }
}

当然在该例子中状态比较少,所以代码看起来也不是很复杂,但是状态如果变多了呢?比如加入换台,快捷键、静音等功能后呢?你会发现条件分支会急速膨胀,所以此时状态设计模式就要登场了

首先,定义抽象状态接口 TVState,将每一个修改状态的动作抽象成一个接口:

public interface TVState {
    void turnOn();
    void turnOff();
    void adjustVolume(int volume);
}

接下来,为每个具体状态创建类,实现 TVState 接口。例如,创建 TVOnStateTVOffState 类:

// 在on状态下,去执行以下各种操作
public class TVOnState implements TVState {
    @Override
    public void turnOn() {
        System.out.println("TV is already on.");
    }

    @Override
    public void turnOff() {
        System.out.println("Turning off the TV.");
    }

    @Override
    public void adjustVolume(int volume) {
        System.out.println("Adjusting volume to: " + volume);
    }
}

// 在关机的状态下执行以下的操作
public class TVOffState implements TVState {
    @Override
    public void turnOn() {
        System.out.println("Turning on the TV.");
    }

    @Override
    public void turnOff() {
        System.out.println("TV is already off.");
    }

    @Override
    public void adjustVolume(int volume) {
        System.out.println("Cannot adjust volume, TV is off.");
    }
}

接下来,定义上下文类 TV

public class TV {
    // 当前状态
    private TVState state;

    public TV() {
        state = new TVOffState();
    }

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

    public void turnOn() {
        // 打开
        state.turnOn();
        // 设置为开机状态
        setState(new TVOnState());
    }

    public void turnOff() {
        // 关闭
        state.turnOff();
        // 设置为关机状态
        setState(new TVOffState());
    }

    public void adjustVolume(int volume) {
        state.adjustVolume(volume);
    }
}

最后,我们可以通过以下方式使用这些类:

public class Main {
    public static void main(String[] args) {
        TV tv = new TV();

        tv.turnOn();
        tv.adjustVolume(10);
        tv.turnOff();
    }
}

这个例子展示了状态模式的基本结构和用法。通过使用状态模式,我们可以更好地组织和管理与特定状态相关的代码。当状态较多时,这种模式的优势就会凸显出来,同时我们在代码时,因为我们会对每个状态进行独立封装,所以也会简化代码编写。