1. 定义

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。它是一种对象行为型模式。

2. 作用

状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。

3. 角色

  • 环境(Context)角色,也叫上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
  • 抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
  • 具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。

4. 实现

举个例子,路口的交通信号灯就有不同的状态,红灯停、绿灯行、黄灯暂停。所以,我们就用状态模式来模拟这个过程。

类图
  1. 定义抽象状态,即红绿灯在亮起时,表现的行为。
public interface ILightState {
    /**
     * 行为表示
     */
    void behave();
}
  1. 定义具体状态,分别是红灯、绿灯和黄灯的实现。
public class RedLight implements ILightState {

    @Override
    public void behave() {
        System.out.println("红灯停");
    }
}

public class GreenLight implements ILightState {

    @Override
    public void behave() {
        System.out.println("绿灯行");
    }
}

public class YellowLight implements ILightState {

    @Override
    public void behave() {
        System.out.println("黄灯亮了等一等");
    }
}
  1. 定义环境角色,交管系统负责信号灯,按照一定的规则进行控制。
public class TrafficSystem {
    private ILightState redLight = new RedLight();
    private ILightState greenLight = new GreenLight();
    private ILightState yellowLight = new YellowLight();

    public void work() {
        double random = Math.random();
        if (random > 0.33) {
            redLight.behave();
        } else if (random > 0.67) {
            greenLight.behave();
        } else {
            yellowLight.behave();
        }
    }
}
  1. 客户角色,信号灯投入使用,并正常运行。
    public static void main(String[] args) {
        TrafficSystem trafficSystem = new TrafficSystem();
        trafficSystem.work();
    }

5. 优缺点

1. 优点:
封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

2. 缺点:
使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足「开闭原则」的要求。

3. 使用场景:
对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为;代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。

参考文章: