设计模式之 状态模式

状态模式(state pattern),通过一个类的内部状态的改变,来改变其行为,这就是状态模式。

状态模式也会定义一系列类簇,每个类中具有转换到下一个状态的逻辑,通过一个统一的上下文类,来使用状态类的功能。

比如我们生活中的红绿灯,红灯亮一段时间转为绿灯,绿灯两一段时间转为黄灯,黄灯两一段时间转为红灯。路口的红绿灯就这样一直循环下去。

涉及角色:

1、抽象状态角色:定义状态行为

2、具体状态角色:实现具体的职责,同时定义状态变化的方式

3、上下文角色:持有状态(保存状态),并使用状态类的功能

我们就以这个例子来看一下代码:

1、定义抽象状态类

package com.itzhimei.study.design.state;

/**
 * www.itzhimei.com
 * 状态模式--状态抽象
 */
public interface IState {

    void doHandle();

    void changeState(Context context);
}

2、定义具体状态类,包括红灯状态、绿灯状态、黄灯状态

package com.itzhimei.study.design.state;

/**
 * www.itzhimei.com
 * 状态模式--红灯
 */
public class RedState implements IState {
    @Override
    public void doHandle() {
        System.out.println("红灯状态");
    }

    @Override
    public void changeState(Context context) {
        System.out.println("------变换状态------");
        context.setState(new GreenState());
    }
}
package com.itzhimei.study.design.state;

/**
 * www.itzhimei.com
 * 状态模式--绿灯
 */
public class GreenState implements IState {
    @Override
    public void doHandle() {
        System.out.println("绿灯状态");
    }

    @Override
    public void changeState(Context context) {
        System.out.println("------变换状态------");
        context.setState(new YellowState());
    }
}
package com.itzhimei.study.design.state;

/**
 * www.itzhimei.com
 * 状态模式--黄灯
 */
public class YellowState implements IState {
    @Override
    public void doHandle() {
        System.out.println("黄灯状态");
    }

    @Override
    public void changeState(Context context) {
        System.out.println("------变换状态------");
        context.setState(new RedState());
    }
}

3、定义上下文类

package com.itzhimei.study.design.state;

/**
 * www.itzhimei.com
 * 状态模式--上下文
 */
public class Context {
    private IState state;

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

    public void doHandle() {
        this.state.doHandle();
        this.state.changeState(this);
    }
}

4、测试

package com.itzhimei.study.design.state;

/**
 * www.itzhimei.com
 * 状态模式--测试
 */
public class Client {

    public static void main(String[] args) {
        IState red = new RedState();
        Context context = new Context();
        context.setState(red);
        context.doHandle();
        context.doHandle();
        context.doHandle();
    }
}

输出结果:

红灯状态
------变换状态------
绿灯状态
------变换状态------
黄灯状态
------变换状态------

类关系图:

我们现在来分析一下代码,在三个红黄绿的状态类中,一个doHandle()方法,是其自己工作的职责,也就是当前是红灯状态,那么红灯就要亮一段时间,来控制哪条路不能通行;另一个changeState(Context context)方法,持有一个上下文类,这个方法是,这个context的作用就是持有变更的状态类,也就是接收不断被更新的状态类,我们demo中按照红灯转绿灯,绿灯转黄灯,黄灯转红灯的顺序,在各自状态类中定义了下一个状态是谁。

最后,我们在main函数中可以看到,通过调用上下文的context.doHandle(),就可以持续产生红绿灯的状态变化。

就好比红绿灯的始终都是这个一个红绿灯,但是通过控制信号,就能持续产生信号灯颜色的变化,这就是状态模式的精髓了。

在应对复杂状态变化的场景,状态模式往往能发挥巨大作用。