前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「聊设计模式」之状态模式(State)

「聊设计模式」之状态模式(State)

原创
作者头像
bug菌
发布2023-11-19 12:20:58
4360
发布2023-11-19 12:20:58
举报

🏆本文收录于《聊计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!


大家下午好,我是bug菌,今天我们继续聊设计模式。

前言

  在软件开发中,我们面临的问题往往是复杂的,要求我们处理多个不同的操作和状态。状态模式(State)是一种处理复杂状态的设计模式,它允许对象在其内部状态发生变化时更改其行为。在本文中,我们将讨论状态模式,提供Java代码示例,并讨论其使用场景和优缺点。

摘要

  状态模式是一种典型的行为型模式,它允许对象在运行时根据内部状态的变化改变自己的行为。状态模式将状态封装成独立的类,并将行为委托给代表当前状态的对象。这使得我们可以在不同的状态下修改对象的行为,从而简化了代码,增强了可维护性和可扩展性。

状态模式

概念

  状态模式是一种行为型设计模式,它允许对象在内部状态发生变化时改变其行为。在状态模式中,一个对象的行为取决于其当前状态,而且可以随时改变这个状态。状态模式将对象的状态封装在不同的状态类中,从而使代码更加清晰和易于维护。当一个对象的状态改变时,状态模式会自动更新该对象的行为,而不需要在代码中手动进行判断和处理。状态模式是一种行为型设计模式,它允许对象在内部状态发生变化时改变其行为。在状态模式中,一个对象的行为取决于其当前状态,而且可以随时改变这个状态。状态模式将对象的状态封装在不同的状态类中,从而使代码更加清晰和易于维护。当一个对象的状态改变时,状态模式会自动更新该对象的行为,而不需要在代码中手动进行判断和处理。

结构

状态模式包含三种类型的角色:

  1. 上下文(**Context**)角色:封装了状态的实例,负责维护状态实例,并将请求委托给当前的状态对象。
  2. 抽象状态(**State**)角色:定义了表示不同状态的接口,并封装了该状态下的行为。所有具体状态都实现这个接口。
  3. 具体状态(**Concrete State**)角色:具体实现了抽象状态角色的接口,并封装了该状态下的行为。

如下是状态模式的UML类图:

应用场景

状态模式适用于以下场景:

  1. 当一个对象的行为取决于它的状态,且它需要在运行时动态切换状态时,可以使用状态模式。
  2. 当一个大的条件分支语句存在于对象的行为中,且这些条件语句在对象的各个方法中都出现,可以使用状态模式将每个条件分支封装为一个状态类。
  3. 当需要添加新的状态时,可以通过添加新的状态类来扩展对象的行为,而不需要修改原有的代码。
  4. 当存在较为复杂的状态转换逻辑时,可以使用状态模式来简化代码,使其易于理解和维护。
  5. 当需要将状态和状态转换与对象的其它行为分离时,可以使用状态模式将状态和状态转换逻辑独立出来。

优缺点

优点

状态模式的优点如下:

  1. 代码简洁,结构清晰:由于状态模式将每个状态封装成了独立的类,使代码结构更加清晰,易于维护和扩展。
  2. 避免了大量的if-else语句:状态模式中的每个状态都可以作为一个单独的类,因此我们不需要使用大量的if-else语句来判断当前对象的状态。
  3. 提高了代码的可维护性:状态模式将状态封装成独立的类,这使得我们可以独立添加或修改状态类,而不会影响其他类的工作。缺点状态模式的缺点如下:
  4. 增加了系统的复杂性:由于状态模式将每个状态封装成了独立的类,因此系统中会出现大量的类,这会增加系统的复杂性。
  5. 无法避免状态转换的复杂性:当状态转换比较复杂时,状态模式并不能帮助我们避免状态转换的复杂性。

状态模式实现

  接下来我们通过一个简单的实例来说明状态模式的实现。

  假设我们正在开发一个交通灯控制系统,交通灯有三个颜色:红色、黄色、绿色,每个颜色代表了交通灯的不同状态,不同的状态需要采取不同的行为。我们使用状态模式来实现这个交通灯控制系统。

  首先,我们定义一个抽象状态类LightState,它包含了所有状态共同拥有的方法:

代码语言:java
复制
package com.example.javaDesignPattern.state;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:10
 */
public abstract class LightState {
    abstract void action();
}

然后,我们实现具体的状态类,如下所示:

代码语言:java
复制
package com.example.javaDesignPattern.state;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:11
 */
public class RedLightState extends LightState{
    @Override
    void action() {
        System.out.println("红灯停");
    }
}
代码语言:java
复制
package com.example.javaDesignPattern.state;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:11
 */
public class YellowLightState extends LightState{
    @Override
    void action() {
        System.out.println("黄灯亮");
    }
}
代码语言:java
复制
package com.example.javaDesignPattern.state;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:11
 */
public class GreenLightState extends LightState{
    @Override
    void action() {
        System.out.println("绿灯行");
    }
}

  最后,我们定义一个上下文类TrafficLight,它维护了当前状态对象,并提供了切换状态的方法:

代码语言:java
复制
package com.example.javaDesignPattern.state;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:11
 */
public class TrafficLight {
    private LightState state;

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

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

  现在,我们就可以使用这些类来实现我们的交通灯控制系统了。我们可以先初始化一个交通灯的对象,然后定义三个相应的状态对象,最后通过改变状态对象来控制交通灯的状态。

代码语言:java
复制
package com.example.javaDesignPattern.state;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:11
 */
public class StateTest {

    public static void main(String[] args) {
        TrafficLight trafficLight = new TrafficLight();

        LightState redLightState = new RedLightState();
        LightState yellowLightState = new YellowLightState();
        LightState greenLightState = new GreenLightState();

        trafficLight.setState(redLightState);
        trafficLight.action();//红灯停

        trafficLight.setState(yellowLightState);
        trafficLight.action();//黄灯亮

        trafficLight.setState(greenLightState);
        trafficLight.action();//绿灯行
    }
}

执行结果如下:

代码方法介绍

  本实例中,共包含4个类LightStateRedLightStateYellowLightStateGreenLightState。其中,LightState是一个抽象类,定义了所有状态共同拥有的方法,RedLightStateYellowLightStateGreenLightState是具体的状态类,它们实现了LightState中定义的方法。

  另外,还有一个上下文类TrafficLight,它维护了当前状态对象,并提供了切换状态的方法。

测试用例

我们使用JUnit来对代码进行测试。测试代码如下:

代码语言:java
复制
import org.junit.Test;
package state;

import com.example.javaDesignPattern.state.*;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/20 15:15
 */
@SpringBootTest
public class StateTest {

    @Test
    public void test() {
        TrafficLight trafficLight = new TrafficLight();

        LightState redLightState = new RedLightState();
        LightState yellowLightState = new YellowLightState();
        LightState greenLightState = new GreenLightState();

        trafficLight.setState(redLightState);
        trafficLight.action();

        trafficLight.setState(yellowLightState);
        trafficLight.action();

        trafficLight.setState(greenLightState);
        trafficLight.action();
    }
}

运行测试用例,我们可以得到以下输出结果:

测试代码成功地演示了状态模式的使用。

测试用例代码解析

  此代码是一个 JUnit 测试类,测试了一个交通信号灯的状态转换。该交通信号灯有三种状态:红灯、黄灯和绿灯。在测试方法中,创建了一个 TrafficLight 对象和三个 LightState 对象,其中 LightState 是一个接口,它有三个实现类:RedLightStateYellowLightStateGreenLightStatestate 对象通过 TrafficLight 对象的 setState() 方法设置,再通过调用 TrafficLight 对象的 action() 方法,执行相应的操作。测试方法在交通信号灯的三种状态间进行切换,以确保状态转换的正确性。

小结

  本文介绍了状态模式,该模式允许对象在其内部状态发生变化时更改其行为。我们先讲述了状态模式的结构和实现,然后讨论了状态模式的优缺点,最后提供了一个使用状态模式的Java示例并进行了测试。

  状态模式是一种十分有用的设计模式,它可以便于维护和扩展代码,并减少复杂的条件判断语句。在实际开发中,我们需要根据具体的场景来选择合适的设计模式,只有在合适的场景下使用合适的设计模式,才能使代码更加优雅和可维护。

附录源码

  如上涉及代码均已上传同步在GitHub,提供给同学们参考性学习。

总结

  本文介绍了状态模式,它是一种处理复杂状态的设计模式,允许对象在其内部状态发生变化时更改其行为。状态模式将状态封装成独立的类,并将行为委托给代表当前状态的对象。这使得我们可以在不同的状态下修改对象的行为,从而简化了代码,增强了可维护性和可扩展性。状态模式适用于当一个对象的行为取决于它的状态,并且需要在运行时动态切换状态的情况。它可以避免大量的if-else语句,并提高代码的可维护性。但是,它也会增加系统的复杂性。最后,本文提供了一个交通灯控制系统的Java代码示例来说明状态模式的实现。

☀️建议/推荐你


  如果想系统性的全面学习设计模式,建议小伙伴们直接毫无顾忌的关注这个专栏《聊设计模式》,无论你是想提升自己的编程技术,还是渴望更好地理解代码背后的设计思想,本专栏都会为你提供实用的知识和启发,帮助你更好地解决日常开发中的挑战,将代码变得更加优雅、灵活和可维护!

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。   同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

📣关于我

  我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 摘要
  • 状态模式
    • 概念
      • 结构
        • 应用场景
          • 优缺点
            • 优点
          • 状态模式实现
            • 代码方法介绍
              • 测试用例
                • 测试用例代码解析
              • 小结
                • 附录源码
                • 总结
                • ☀️建议/推荐你
                • 📣关于我
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档