津津乐道设计模式 - 状态模式详解(以交通信号灯举例带你快速理解)

news2024/9/24 1:21:11

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

津津乐道设计模式 - 状态模式详解

  • 什么是状态模式
  • 状态模式适用场景
  • 生活案例
  • 案例代码
  • 状态模式优缺点
  • 结语

什么是状态模式

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为。状态模式将对象的行为封装在不同的状态类中,并通过上下文对象来管理状态的切换。
在这里插入图片描述

在状态模式中,有以下几个关键角色:

上下文(Context):维护一个对当前状态对象的引用,并提供接口给客户端来请求状态的改变。

抽象状态(State):定义一个通用的状态接口,具体的状态类实现这个接口,并根据具体的状态来实现相应的行为。

具体状态(Concrete State):实现抽象状态接口,定义该状态下的具体行为。

状态模式的核心思想是将对象的行为和状态解耦,使得对象的行为可以根据内部状态的变化而变化,同时遵循开闭原则,易于扩展。

状态模式适用场景

  • 当一个对象的行为取决于其内部状态,并且在运行时需要根据状态来改变行为时,可以使用状态模式 (比如:订单状态)

  • 当对象的行为有多个状态且频繁发生变化时,可以使用状态模式来减少大量的条件判断语句 (比如:商品库存状态)

  • 当需要在运行时动态地添加新的状态,并且能够轻松地扩展状态类时,可以使用状态模式

  • 当对象具有较复杂的状态转换逻辑时,可以使用状态模式来简化状态之间的转换关系

状态模式通过将对象的行为和状态进行分离,使得状态的变化可以独立于行为,从而提高了代码的可维护性和扩展性。它适用于对象具有多个状态且需要根据不同状态来改变行为的场景。

生活案例

在一个交通信号灯系统中,交通信号灯可以处于不同的状态,比如红灯、绿灯和黄灯。每个状态下交通信号灯的行为和显示都是不同的,我们可以使用状态模式来实现这个场景,让大家更容易理解状态模式;
在这里插入图片描述

案例代码

首先,我们定义一个状态接口(State),其中包含了交通信号灯的行为方法,比如显示信号灯、处理信号灯变化等:

// 状态接口
public interface State {
    void displaySignal();
    void handleSignalChange(TrafficSignal signal);
}

我们定义交通信号灯类(TrafficSignal)作为上下文,包含当前的状态对象,并提供了一些方法来控制信号灯的行为:

// 交通信号灯类
public class TrafficSignal {
    private State state;

    public TrafficSignal() {
        // 初始状态为红灯
        this.state = new RedLightState();
    }

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

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

    public void changeSignal() {
        state.handleSignalChange(this);
    }
}

然后,我们定义具体的状态类,分别表示红灯、绿灯和黄灯:

// 红灯状态
public class RedLightState implements State {
    @Override
    public void displaySignal() {
        System.out.println("红灯亮起");
    }

    @Override
    public void handleSignalChange(TrafficSignal signal) {
        signal.setState(new GreenLightState());
    }
}

// 绿灯状态
public class GreenLightState implements State {
    @Override
    public void displaySignal() {
        System.out.println("绿灯亮起");
    }

    @Override
    public void handleSignalChange(TrafficSignal signal) {
        signal.setState(new YellowLightState());
    }
}

// 黄灯状态
public class YellowLightState implements State {
    @Override
    public void displaySignal() {
        System.out.println("黄灯亮起");
    }

    @Override
    public void handleSignalChange(TrafficSignal signal) {
        signal.setState(new RedLightState());
    }
}

现在,我们可以在客户端中使用交通信号灯系统:

public class Client {
    public static void main(String[] args) {
        TrafficSignal signal = new TrafficSignal();

        // 显示当前信号灯状态
        signal.displaySignal();

        // 切换信号灯状态
        signal.changeSignal();

        // 显示切换后的信号灯状态
        signal.displaySignal();
    }
}

最终代码结构如下:
在这里插入图片描述
执行效果:

在这里插入图片描述

在上述代码中,我们通过创建交通信号灯对象并调用相应的方法来控制交通信号灯的行为。通过改变状态对象,交通信号灯的行为和显示也随之改变。

通过使用状态模式,我们可以实现交通信号灯系统的灵活状态转换,将每个状态的行为和显示进行了封装,使得代码结构清晰、易于维护和扩展。

状态模式优缺点

状态模式的优点:

  • 简化了条件语句:状态模式能够将复杂的条件判断逻辑封装在状态类中,使得代码结构更清晰,易于理解和维护。

  • 提高了扩展性:当需要添加新的状态时,只需要创建新的状态类并实现状态接口,而不需要修改现有的代码。状态模式符合开闭原则,使得系统的可扩展性更好。

  • 将状态局部化:状态模式将对象的状态局部化,使得每个状态都有自己的方法,可以更好地控制和管理对象的状态。

  • 提高了代码可读性:状态模式使得状态和行为关联紧密,可以更清晰地表达对象的行为和状态转换逻辑,提高了代码的可读性。

状态模式的缺点:

  • 增加了类的数量:引入状态模式会增加多个状态类,可能会使得类的数量增多,增加了系统的复杂性。

  • 状态转换逻辑复杂:如果状态之间的转换逻辑比较复杂,可能会增加状态模式的实现难度。

  • 不适合状态较少或状态稳定的情况:如果对象的状态较少或者状态变化较少,使用状态模式可能会显得过于繁琐。

状态模式适用于具有多个状态且状态转换逻辑较复杂的场景,能够很好地解决对象的状态管理和状态转换问题。在使用时需要权衡其优点和缺点,并根据具体场景来选择是否使用状态模式。

结语

本章节主要介绍了状态模式、状态模式适用场景、状态模式的优缺点,并以交通信号灯举例模仿状态模式的使用方法,如果本文对你有用,欢迎关注收藏评论,后续将陆续推出贴切生活的搞笑讲解方式带大家一起学编程~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/739312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Anaconda删除虚拟环境

# 查看环境,确定待删除环境位置 conda env list# 按照位置进行删除 conda env remove -p 要删除的虚拟环境路径举例: 删除py37执行如下命令: conda env remove -p D:\A\envs\py37

【GAN】基础知识(还在更新)

还没写完,别骂了.....遇到啥新东西也会补充进来 1. 损失函数/距离度量 1.1 KL散度 用来衡量分布之间距离 1.1.1 推导过程 如果想要对KL散度有一个比较好的理解,我其实建议看一下,从信息熵的角度入手我认为是一个比较好的切入点 相对熵&a…

RC-u5 树与二分图(二分图)

PTA | 程序设计类实验辅助教学平台 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N2e610; int st[N]; ll n,m;//数据可能超int int h[N],ne[N],e[N],idx; void add(int a,int b) {e[idx]b,ne[idx]h[a],h[a]idx; } void dfs(int v,int co…

基于Web的数字孪生智慧养老院可视化云平台

前言 我国已经迈入老龄化社会&#xff0c;老龄化社会中养老已然成为社会普遍关注的焦点&#xff0c;智慧养老成为未来趋势。 建设背景 社会因素 养老床位数量也增长至2020年的821万张.每千名老人拥有养老床位增长至35张,相对于先进国家的50-7O张仍有较大差距。目前养老床位…

python_day4

def test():return 1, a, Truex, y, z test() print(f"x{x},y{y},z{z}")位置参数&#xff1a;调用时根据参数位置传递参数 关键字参数&#xff1a;调用时通过“键值”形式传参 def user(name, age, gender):print(f"name:{name},age:{age},gender:{gender}&q…

Python django开发

第一步&#xff1a;创建开发环境 mkvirtualenv py2_django 第二步&#xff1a;安装django pip install django2.2.5 # 选择2.2.5的原因是这个版本是持久维护的 pip list # 查看安装的信息 第三步&#xff1a;start 一个项目&#xff0c;并创建子应用 cd ~/Myproject # 选择…

4.2 图书借阅系统数据库设计 --MySQL

本文目录 前言一、背景和需求分析1.1 背景1.2 信息需求1.3 功能需求管理员学生 1.4 数据流图 二、概念结构设计1. 抽象出系统实体2. 局部E-R图2.1 学生 E-R图2.2 借阅证 E-R图2.3 图书 E-R图2.4 管理员 E-R图2.5 公告 E-R图2.6 申请 E-R图2.7 借阅 E-R图2.8 评论 E-R图2.9 收藏…

❤ Vue2+vue-cli+vue-router+vuex +elementUI/vant完整项目搭建 项目和配置(一)

Vue2vue-clivue-routervuex elementUI/vant项目搭建和配置webpack&#xff08;一&#xff09; 项目整套&#xff1a;Vue2vue-clivue-routervuex elementUI/vant 1、环境检测&#xff1a; node 环境 git --version git 环境 git --version npm 环境 npm -v 查看VUE脚手架版本 …

响应式编程实战(02)-响应式编程的适用场景

0 知识前提 已掌握响应式编程中的核心概念&#xff1a;响应式流、背压机制以及响应式流规范。 1 引言 响应式编程能够应用到那些具体的场景呢? 目前有哪些框架中使用到了这一新型的技术体系呢? 2 响应式编程的应用场景分析 可以认为响应式编程并不仅仅是一种编程技术&a…

OpenPCDet系列 | 8.1 nuScenes数据集的处理流程与gt_sample的database构建

1. nuScenes Dataloader 对nuScenes数据集处理的了解&#xff0c;大体上的核心还是getitem函数、prepare_data函数&#xff0c;以及collate_batch函数三个部分的处理。其中prepare_data函数和collate_batch函数是在Dataset这个父类实现的&#xff0c;基本的处理流程基本不变&a…

《Redis 核心技术与实战》课程学习笔记(六)

哨兵集群 哨兵机制的基本流程 在 Redis 主从集群中&#xff0c;哨兵机制是实现主从库自动切换的关键机制。 哨兵其实就是一个运行在特殊模式下的 Redis 进程&#xff0c;主从库实例运行的同时&#xff0c;它也在运行。哨兵主要负责的就是三个任务&#xff1a;监控、选主&…

三种SQL实现聚合字段合并(presto、hive、mysql)

需求&#xff1a;按照项目名&#xff0c;以逗号合并参与人 presto select item_name,array_join(array_agg(name),,) as group_name from test.test_04 group by item_name order by item_name hive select item_name,concat_ws(,,collect_set(name)) as group_name from tes…

全志V3S嵌入式驱动开发(四种启动方式)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 对于v3s的启动方式分析,怎么研究都不为过。对我们整个系列文章比较熟悉的同学来说,这幅图真的是太熟悉了, 整个流程不复杂。它主要是告诉我们,v3s加载的顺序是怎么样的…

【Linux后端服务器开发】进程控制与替换

目录 一、进程控制 1. 进程退出 2. 进程等待 2.1 阻塞等待 2.2 status位图结构 2.3 非阻塞等待 二、进程替换 1. exec*系列函数 2. 进程替换高级语言可执行程序 一、进程控制 1. 进程退出 进程退出会进入僵尸态&#xff0c;把自己的退出结果写入到自己的task_struct…

一种使得大模型输出结构化数据的简易方法

最近在用大模型跑一些数据&#xff0c;于是就不可避免的遇到了如何让大模型输出的格式便于处理这个问题。经过一些研究发现了一套比较有用的方法&#xff0c;在这里总结一下。 背景 任务是这样的&#xff0c;我需要用大模型&#xff08;比如ChatGPT&#xff0c;ChatGLM等等&a…

Springboot启用HTTP响应压缩

官方文档:https://docs.spring.io/spring-boot/docs/2.3.12.RELEASE/reference/htmlsingle/#how-to-enable-http-response-compression

Java面试题大全(2023牛客网最新版)大厂面试题附答案详解

很多 Java 工程师的技术不错&#xff0c;但是一面试就头疼&#xff0c;10 次面试 9 次都是被刷&#xff0c;过的那次还是去了家不知名的小公司。 问题就在于&#xff1a;面试有技巧&#xff0c;而你不会把自己的能力表达给面试官。 应届生&#xff1a;你该如何准备简历&#…

解决mysql的count()函数条件表达式不生效的问题

示例 表数据 统计错误的sql select count(age 10) as count from student查询结果 原因 count(‘任意内容’)都会统计出所有记录数&#xff0c;因为count只有在遇见null时才不计数&#xff0c;即count(null)0 解决 方法1&#xff1a;count()函数中条件表达式加上or n…

1、计算机网络核心

序号地址1计算机网络核心2数据库相关3Redis4Linux相关5JVM的内容6GC相关的7Java多线程与并发8Java多线程与并发-原理9Java常用类库与技巧10Java框架-Spring 文章目录 1、OSI开放式互联参考模型2、TCP/IP3、TCP报文头4、TCP的三次握手5、TCP的四次挥手6、为什么会有TIME_WAIT状态…

【unity】燧光MR设备极简教程(使用篇)

燧光MR设备极简教程&#xff08;使用篇&#xff09; 一、硬件的基础使用二、定位信标三、投屏直播1、第三人称视角同步MR2、第一人称视角无线投屏 相关文章&#xff1a;燧光MR设备极简教程&#xff08;开发篇&#xff09; 一、硬件的基础使用 官方使用文档&#xff1a;https:…