初探设计模式之【状态设计模式】

初探设计模式之【状态】

一、场景

这里从一个例子开始引入状态设计模式。

以交通信号灯为例,有红、黄、绿三种颜色的信号灯,绿灯显示一段时间后,短暂切换到黄灯后,再切换到红灯。红灯显示一段一段时候,再短暂切换到黄灯,再切换到绿灯。总之,红灯和绿灯之间不能直接切换,需要借助黄灯转换一下。

我们需要实现一个交通信号灯,分别切换到红、黄、绿灯的方法。

二、传统实现

这样一种场景,如果使用传统的写法,大致可能是如下的思路:

切换到红灯:如果当前为 “红” , 则报错,因为当前已经是红灯了。如果当前是绿灯,也报错,因为绿灯不能直接切换到红灯。最后只剩下黄灯,黄灯可以切换红灯,让黄灯亮2秒钟。

切换到黄灯:如果当前为 “黄”,则报错,因为当前已经是黄灯了。否则,可以切换到黄灯,红灯或绿灯亮 6 秒。

剩下的就不列举了。

上面例子的每一个切换方法中,都需要写一系列的判断逻辑,这里你也许会说好像也还好,但如果状态变多,规则变复杂写,这里的一系列 if else 可能就很难看了,而且所有的逻辑都集中在一个类中,一堆的逻辑判断,很让人抓狂。我们可以尝试用状态模式来实现。

三、应用状态模式

将切换状态的行为抽取出来,编写一个 State 接口:

public interface State {

    //切换到红灯
    void switchToRed(TrafficLight trafficLight);

    //切换到黄灯
    void switchToYellow(TrafficLight trafficLight);

    //切换到绿灯
    void switchToGreen(TrafficLight trafficLight);
}

然后我们分别将红黄绿灯实现:

//红灯
public class RedState implements State{

    @Override
    public void switchToRed(TrafficLight trafficLight) {
        System.out.println("ERROR! 已经是红灯了");
    }

    @Override
    public void switchToYellow(TrafficLight trafficLight) {
        trafficLight.setState(new YellowState());
        System.out.println("黄灯亮 2 秒");
        ThreadUtil.sleep(2_000);
    }

    @Override
    public void switchToGreen(TrafficLight trafficLight) {
        System.out.println("ERROR! 红灯不能直接切换为绿灯!");
    }
}

//黄灯
public class YellowState implements State {

    @Override
    public void switchToRed(TrafficLight trafficLight) {
        trafficLight.setState(new RedState());
        System.out.println("红灯亮 6 秒");
        ThreadUtil.sleep(6_000);
    }

    @Override
    public void switchToYellow(TrafficLight trafficLight) {
        System.out.println("已经是黄灯");
    }

    @Override
    public void switchToGreen(TrafficLight trafficLight) {
        trafficLight.setState(new GreenState());
        System.out.println("绿灯亮 6 秒");
        ThreadUtil.sleep(6_000);
    }
}

//绿灯
public class GreenState implements State {

    @Override
    public void switchToRed(TrafficLight trafficLight) {
        System.out.println("ERROR! 红灯不能直接切换为绿灯!");
    }

    @Override
    public void switchToYellow(TrafficLight trafficLight) {
        trafficLight.setState(new YellowState());
        System.out.println("黄灯亮 2 秒");
        ThreadUtil.sleep(2_000);
    }

    @Override
    public void switchToGreen(TrafficLight trafficLight) {
        System.out.println("ERROR! 已经是绿灯了!");
    }
}

TrafficLight 表示交通信号灯,它需要实现切换信号灯的功能:

public class TrafficLight {
    private State state = new GreenState();

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

    public void switchToRed() {
        state.switchToRed(this);
    }

    public void switchToYellow(){
        state.switchToYellow(this);
    }

    public void switchToGreen() {
        state.switchToGreen(this);
    }
}

在交通信号灯类中,我们不再需要实现复杂的状态判断,转而由状态自己去切换,而每种状态又有各自自己的实现,即每种灯切换到别的灯应该怎么处理,相比原有的判断逻辑,这样一下子变得清爽了不少。

看下打印结果:

黄灯亮 2 秒
红灯亮 6 秒
黄灯亮 2 秒
绿灯亮 6 秒
黄灯亮 2 秒
红灯亮 6 秒

Process finished with exit code 0

四、理解

状态模式的应用将系统状态从系统环境中彻底抽离出来,状态接口确立了高层统一规范,使状态响应机制分立、自治,以一种松耦合的方式实现了系统状态与行为的联动机制(每种状态自己去处理当前状态应该处理的逻辑)。

状态模式的类结构如下:

State(状态接口):定义通用的状态规范标准,其中处理请求方法handle()将系统环境Context作为参数传入。对应本章例程中的状态接口State。

ConcreteStateA、ConcreteStateB、ConcreteStateC(状态实现A、状态实现B、状态实现C):具体的状态实现类,根据系统环境用于表达系统环境Context的各个状态,它们都要符合状态接口的规范。对应本章例程中的红灯状态Red、绿灯状态Green以及黄灯状态Yellow。

Context(系统环境):系统的环境,持有状态接口的引用,以及更新状态方法setState(),对外暴露请求发起方法request(),对应本章例程中的交通灯类 TrafficLight

注:本文参考了 《秒懂设计模式》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值