当前位置: 首页 > news >正文

【设计模式-行为型】状态模式

一、什么是状态模式

        什么是状态模式呢,这里我举一个例子来说明,在自动挡汽车中,挡位的切换是根据驾驶条件(如车速、油门踏板位置、刹车状态等)自动完成的。这种自动切换挡位的过程可以很好地用状态模式来描述。状态模式(State Pattern) 是一种行为型设计模式,它允许一个对象在其内部状态发生变化时(加速或者减速)改变其行为(换挡)。状态模式的核心思想是将对象的行为封装在不同的状态类中,使得对象的行为随着状态的改变而改变。这种模式特别适用于对象的行为依赖于其内部状态的场景。

二、为什么使用状态模式

  1. 清晰的职责划分:代码结构清晰,每个状态类的职责单一,易于理解和维护。例如,在自动挡汽车中,每个挡位的行为都封装在独立的状态类中,职责划分明确。

  2. 动态改变行为:减少了复杂的条件分支(如 if-elseswitch-case),使代码更加简洁和可读。例如,在自动挡汽车中,换挡逻辑由状态机自动处理,无需在主逻辑中写复杂的条件判断。

  3. 扩展性:符合开闭原则(对扩展开放,对修改封闭)。例如,在自动挡汽车中,新增一个挡位(如6挡)时,只需添加一个新的状态类,无需修改现有的换挡逻辑。

  4. 低耦合:状态类和上下文类之间的依赖关系减少,提高了代码的灵活性和可维护性。例如,在自动挡汽车中,Car 类与各个挡位状态类通过 GearState 接口交互,降低了耦合度。

  5. 适应复杂状态逻辑:能够清晰地表达状态转换逻辑,避免代码混乱。例如,在自动挡汽车中,换挡逻辑可能涉及多种条件(如车速、油门位置等),状态机模式能够清晰地表达这些逻辑。

三、状态模式的示例

3.1 状态模式示例及角色

1. State:定义状态接口(行为)

定义了所有挡位状态的通用接口,包含所有挡位共有的方法,例如加速、减速等

public interface GearState {void accelerate(Car car); // 加速时的行为void decelerate(Car car); // 减速时的行为
}

2. ConcreteState:实现具体状态类(档位)

每个挡位(如1挡、2挡、3挡、4挡、5挡等)都实现状态接口,并定义在该挡位下的行为。

public class FirstGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前1档:加速...");car.setState(new SecondGear()); // 切换到2挡}@Overridepublic void decelerate(Car car) {System.out.println("当前1档:减速...");car.setState(new NeutralGear()); // 切换到空挡}
}public class SecondGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前2档:加速...");car.setState(new ThirdGear()); // 切换到3挡}@Overridepublic void decelerate(Car car) {System.out.println("当前2档:减速...");car.setState(new FirstGear()); // 切换到1挡}
}public class ThirdGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前3档:加速...");car.setState(new FourthGear()); // 切换到4挡}@Overridepublic void decelerate(Car car) {System.out.println("当前3档:减速...");car.setState(new SecondGear()); // 切换到2挡}
}public class FourthGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前4档:加速...");car.setState(new FifthGear()); // 切换到5挡}@Overridepublic void decelerate(Car car) {System.out.println("当前1档:减速...");car.setState(new ThirdGear()); // 切换到3挡}
}public class FifthGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前5档:加速...");// 保持在5挡}@Overridepublic void decelerate(Car car) {System.out.println("当前5档:减速...");car.setState(new FourthGear()); // 切换到4挡}
}public class NeutralGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前空档:加速...");car.setState(new FirstGear()); // 切换到1挡}@Overridepublic void decelerate(Car car) {System.out.println("当前空档:减速...");// 保持在空挡}
}

3、Context(上下文):(当前车辆,记录当前状态)

上下文可以被视为汽车的驾驶系统,它包含当前挡位的状态,并根据驾驶员的操作切换挡位

public class Car {private GearState currentState;public Car() {this.currentState = new NeutralGear(); // 初始状态为空挡}public void setState(GearState state) {this.currentState = state;}public void accelerate() {currentState.accelerate(this);}public void decelerate() {currentState.decelerate(this);}
}

4、场景(开车)

public class Main {public static void main(String[] args) {Car car = new Car();car.accelerate(); // 初始状态为空挡,加速后切换到1挡car.accelerate(); // 当前状态为1挡,加速后切换到2挡car.accelerate(); // 当前状态为2挡,加速后切换到3挡car.decelerate(); // 当前状态为3挡,减速后切换到2挡car.decelerate(); // 当前状态为2挡,减速后切换到1挡car.decelerate(); // 当前状态为1挡,减速后切换到空挡}
}//输出
当前0档:加速...
当前1档:加速...
当前2档:加速...
当前3档:加速...
当前3档:减速...
当前2档:减速...
当前1档:减速...
当前0档:减速...

3.2 在JAVA开发中常用的Spring状态机

        在Spring框架中,可以使用Spring State Machine来实现状态机模式。Spring State Machine是一个功能强大的状态机框架,支持定义状态、事件和状态转换,并且可以与Spring生态系统无缝集成。在实际开发中,可能使用Spring框架比较多,一般都是直接使用现成的Spring State Machine 来实现状态模式。

1、集成依赖包

<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>2.1.3.RELEASE</version>
</dependency>

2、定义状态和事件

//车辆档位枚举类
public enum CarState {NEUTRAL,     //空挡FIRST_GEAR,  //一档SECOND_GEAR, //二挡THIRD_GEAR,  //三挡FOURTH_GEAR, //四挡FIFTH_GEAR;   //五档
}//车辆行为枚举类
public enum CarEvent {ACCELERATE,     //加速行为DECELERATE;     //减速行为
}

3、配置状态机

@Configuration
@EnableStateMachine(name="carStateMachine")
public class CarStateMachineConfig extends StateMachineConfigurerAdapter<CarState, CarEvent> {public void configure(StateMachineStateConfigurer<CarState, CarEvent> states) throws Exception {states.withStates().initial(CarState.NEUTRAL).states(EnumSet.allOf(CarState.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<CarState, CarEvent> states) throws Exception {states.withExternal().source(CarState.NEUTRAL).target(CarState.FIRST_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.FIRST_GEAR).target(CarState.SECOND_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.SECOND_GEAR).target(CarState.THIRD_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.THIRD_GEAR).target(CarState.FOURTH_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.FOURTH_GEAR).target(CarState.FIFTH_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.FIFTH_GEAR).event(CarEvent.ACCELERATE) // No change.and().withExternal().source(CarState.FIFTH_GEAR).target(CarState.FOURTH_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.FOURTH_GEAR).target(CarState.THIRD_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.THIRD_GEAR).target(CarState.SECOND_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.SECOND_GEAR).target(CarState.FIRST_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.FIRST_GEAR).target(CarState.NEUTRAL).event(CarEvent.DECELERATE);}// 配置状态机持久化@Beanpublic DefaultStateMachinePersister machinePersister() {return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Car>() {@Overridepublic void write(StateMachineContext<Object, Object> stateMachineContext, Car car) throws Exception {//持久化操作。可以通过任何形式进行持久化。redis 、 mongodb、mysql,ecache}@Overridepublic StateMachineContext<Object, Object> read(Car car) throws Exception {// 从持久化组件里进行读取return new DefaultStateMachineContext(car.getCarState(), null, null, null);}});}
}

4、定义状态监听器

        在Spring State Machine中,可以通过@WithStateMachine注解和@OnTransition注解来定义状态监听器。这些监听器会在状态转换时被触发。

// 监听器是监听到 action 后进行状态的一个变更。
@Slf4j
@Component("carStateListener")
@WithStateMachine(name="carStateMachine")
public class CarStateListener {@OnTransition(source = "NEUTRAL", target = "FIRST_GEAR")public boolean onAccelerateFromNeutral(Message<CarEvent> message) {log.info("Accelerating from NEUTRAL to FIRST_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FIRST_GEAR);return true;}@OnTransition(source = "FIRST_GEAR", target = "SECOND_GEAR")public boolean onAccelerateFromFirstGear(Message<CarEvent> message) {log.info("Accelerating from FIRST_GEAR to SECOND_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.SECOND_GEAR);return true;}@OnTransition(source = "SECOND_GEAR", target = "THIRD_GEAR")public boolean onAccelerateFromSecondGear(Message<CarEvent> message) {log.info("Accelerating from SECOND_GEAR to THIRD_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.THIRD_GEAR);return true;}@OnTransition(source = "THIRD_GEAR", target = "FOURTH_GEAR")public boolean onAccelerateFromThirdGear(Message<CarEvent> message) {log.info("Accelerating from THIRD_GEAR to FOURTH_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FOURTH_GEAR);return true;}@OnTransition(source = "FOURTH_GEAR", target = "FIFTH_GEAR")public boolean onAccelerateFromFourthGear(Message<CarEvent> message) {log.info("Accelerating from FOURTH_GEAR to FIFTH_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FIFTH_GEAR);return true;}@OnTransition(source = "FIFTH_GEAR", target = "FOURTH_GEAR")public boolean onDecelerateFromFifthGear(Message<CarEvent> message) {log.info("Decelerating from FIFTH_GEAR to FOURTH_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FOURTH_GEAR);return true;}@OnTransition(source = "FOURTH_GEAR", target = "THIRD_GEAR")public boolean onDecelerateFromFourthGear(Message<CarEvent> message) {log.info("Decelerating from FOURTH_GEAR to THIRD_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.THIRD_GEAR);return true;}@OnTransition(source = "THIRD_GEAR", target = "SECOND_GEAR")public boolean onDecelerateFromThirdGear(Message<CarEvent> message) {log.info("Decelerating from THIRD_GEAR to SECOND_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.SECOND_GEAR);return true;}@OnTransition(source = "SECOND_GEAR", target = "FIRST_GEAR")public boolean onDecelerateFromSecondGear(Message<CarEvent> message) {log.info("Decelerating from SECOND_GEAR to FIRST_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FIRST_GEAR);return true;}@OnTransition(source = "FIRST_GEAR", target = "NEUTRAL")public boolean onDecelerateFromFirstGear(Message<CarEvent> message) {log.info("Decelerating from FIRST_GEAR to NEUTRAL");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.NEUTRAL);return true;}}

4、使用状态机

@Service
public class CarService {@Resourceprivate StateMachine<CarState, CarEvent> carStateMachine;@Resourceprivate StateMachinePersister<CarState, CarEvent, Car> carMachinePersister;//模拟一个存储private Car car = new Car();//加速方法public Car acc() {if (car.getCarState() == null){car.setCarState(CarState.NEUTRAL);}// 书写逻辑Message message = MessageBuilder.withPayload(CarEvent.ACCELERATE).setHeader("car", car).build();if(changeStateAction(message,car)) {return car;}return car;}//减速方法public Car dece() {if (car.getCarState() == null){car.setCarState(CarState.NEUTRAL);}// 书写逻辑Message message = MessageBuilder.withPayload(CarEvent.DECELERATE).setHeader("car", car).build();if(changeStateAction(message,car)) {return car;}return car;}private boolean changeStateAction(Message<CarEvent> message, Car car) {try {carStateMachine.start();//尝试恢复状态机状态carMachinePersister.restore(carStateMachine, car); // 待议boolean res = carStateMachine.sendEvent(message);//持久化状态机状态carMachinePersister.persist(carStateMachine, car); // 持久return res;} catch (Exception e) {e.printStackTrace();} finally {carStateMachine.stop();}return false;}
}

4、场景(开车)

@SpringBootApplication
public class CarApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(DesignApplication.class, args);CarService carService = context.getBean(CarService.class);Car car;car = carService.acc(); // 初始状态为空挡,加速后切换到1挡System.out.println("After accelerate: " + car.getCarState());car = carService.acc(); // 当前状态为1挡,加速后切换到2挡System.out.println("After accelerate: " + car.getCarState());car = carService.dece(); // 当前状态为2挡,减速后切换到1挡System.out.println("After decelerate: " + car.getCarState());car = carService.dece(); // 当前状态为1挡,减速后切换到空挡System.out.println("After decelerate: " + car.getCarState());}
}//输出
After accelerate: FIRST_GEAR
After accelerate: SECOND_GEAR
After decelerate: FIRST_GEAR
After decelerate: NEUTRAL

相关文章:

【设计模式-行为型】状态模式

一、什么是状态模式 什么是状态模式呢&#xff0c;这里我举一个例子来说明&#xff0c;在自动挡汽车中&#xff0c;挡位的切换是根据驾驶条件&#xff08;如车速、油门踏板位置、刹车状态等&#xff09;自动完成的。这种自动切换挡位的过程可以很好地用状态模式来描述。状态模式…...

2024.1.22 安全周报

政策/标准/指南最新动态 01 工信部印发《关于加强互联网数据中心客户数据安全保护的通知》 原文: https://www.secrss.com/articles/74673 互联网数据中心作为新一代信息基础设施&#xff0c;承载着千行百业的海量客户数据&#xff0c;是关系国民经济命脉的重要战略资源。…...

idea修改模块名导致程序编译出错

本文简单描述分别用Idea菜单、pom.xml文件管理项目模块module 踩过的坑&#xff1a; 通过idea菜单创建模块&#xff0c;并用idea菜单修改模块名&#xff0c;结构程序编译报错&#xff0c;出错的代码莫名奇妙。双击maven弹窗clean时&#xff0c;还是报错。因为模块是新建的&am…...

root用户Linux银河麒麟服务器安装vnc服务

安装必要桌面环境组件 yum install mate-session-manager -y mate-session #确定是否安装成功安装vnc服务器 yum install tigervnc-server -y切换到root为root得vnc设置密码 su root vncpasswd给root用户设置vnc服务器文件 vi /etc/systemd/system/vncserver:1.service [Un…...

CentOS 7使用RPM安装MySQL

MySQL是一个开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;允许用户高效地存储、管理和检索数据。它被广泛用于各种应用&#xff0c;从小型的web应用到大型企业解决方案。 MySQL提供了丰富的功能&#xff0c;包括支持多个存储引擎、事务能力、数据完整…...

OpenCV imread函数读取图像__实例详解

OpenCV imread函数读取图像__实例详解 本文目录&#xff1a; 零、时光宝盒 一、imread函数定义 二、imread函数支持的文件格式 三、imread函数flags参数详解 &#xff08;3.1&#xff09;、Flags-1时&#xff0c;样返回加载的图像&#xff08;使用alpha通道&#xff0c;否…...

激光线扫相机无2D图像的标定方案

方案一&#xff1a;基于运动控制平台的标定 适用场景&#xff1a;若激光线扫相机安装在可控运动平台&#xff08;如机械臂、平移台、旋转台&#xff09;上&#xff0c;且平台的运动精度已知&#xff08;例如通过编码器或高精度步进电机控制&#xff09;。 步骤&#xff1a; 标…...

【安当产品应用案例100集】034-安当KSP支持密评中存储数据的机密性和完整性

安当KSP是一套获得国密证书的专业的密钥管理系统。KSP的系统功能扩展图示如下&#xff1a; 我们知道商用密码应用安全性评估中&#xff0c;需要确保存储的数据不被篡改、删除或者破坏&#xff0c;必须采用合适的安全方案来确保存储数据的机密性和完整性。KSP能否满足这个需求呢…...

08.七种排序算法实现(C语言)

目录 一.排序的基本概念 1.1 排序的概念 1.2 常见的排序算法 二.常见排序算法的实现 2.1 插入排序&#xff08;直接&#xff09; 1.基本思想 2.直接插入排序的特性 3.代码实现 2.2 希尔排序 1.基本思想 2.希尔插入排序的特性 3.代码实现 2.3 选择排序 1.基本思想 2…...

Alibaba Spring Cloud 一 核心组件、特性

Alibaba Spring Cloud 是 Alibaba 基于 Spring Cloud 的分布式微服务解决方案&#xff0c;提供了一套高性能、高可靠的微服务开发和运维工具。它扩展了 Spring Cloud 的功能&#xff0c;并优化了许多在生产环境中的实践场景&#xff0c;例如服务发现、配置管理、熔断限流等。 …...

kafka学习笔记7 性能测试 —— 筑梦之路

kafka 不同的参数配置对 kafka 性能都会造成影响&#xff0c;通常情况下集群性能受分区、磁盘和线程等影响因素&#xff0c;因此需要进行性能测试&#xff0c;找出集群性能瓶颈和最佳参数。 # 生产者和消费者的性能测试工具 kafka-producer-perf-test.sh kafka-consumer-perf-t…...

HQChart使用教程30-K线图如何对接第3方数据45- DRAWRADAR数据结构

HQChart使用教程30-K线图如何对接第3方数据45- DRAWRADAR数据结构 效果图DRAWRADARHQChart代码地址后台数据对接说明示例数据数据结构说明效果图 DRAWRADAR DRAWRADAR是hqchart插件独有的绘制雷达图函数,可以通过麦语法脚本来绘制一个简单的雷达图数据。 雷达图显示的位置固定…...

Java集合学习:HashMap的原理

一、HashMap里的Hash是什么&#xff1f; 首先&#xff0c;我们先要搞清楚HashMap里的的Hash是啥意思。 当我们在编程过程中&#xff0c;往往需要对线性表进行查找操作。 在顺序表中查找时&#xff0c;需要从表头开始&#xff0c;依次遍历比较a[i]与key的值是否相等&#xff…...

ETLCloud在iPaas中的是关键角色?

在当今的数字化时代&#xff0c;企业越来越依赖于其处理和分析数据的能力。为了实现这一目标&#xff0c;企业需要将各种异构的应用和数据源集成在一起&#xff0c;形成一个统一的数据视图。在这一过程中&#xff0c;ETL&#xff08;Extract, Transform, Load&#xff09;和iPa…...

Docker Hub 全面解析及应对策略

在现代 DevOps 和容器化应用开发中&#xff0c;Docker Hub 是一个不可或缺的工具。然而&#xff0c;一些地区或企业对 Docker Hub 的访问受到限制&#xff0c;甚至全面禁止。这种现象引发了开发者和运维人员的广泛关注。那么&#xff0c;为什么 Docker Hub 会被禁用&#xff1f…...

第五天 Labview数据记录(5.1 INI配置文件读写)

5.1 INI配置文件读写 INI配置文件是一种简单的文本文件&#xff0c;通常用于存储软件的配置信息。它具有以下作用&#xff1a; 存储软件配置参数方便软件的维护和更新提高软件的灵活性和可扩展性便于用户修改和共享配置 5.1.1 前面板 1&#xff09;新建项目SaveData_Exampl…...

【算法】经典博弈论问题——巴什博弈 python

目录 前言巴什博弈(Bash Game)小试牛刀PN分析实战检验总结 前言 博弈类问题大致分为&#xff1a; 公平组合游戏、非公平组合游戏&#xff08;绝大多数的棋类游戏&#xff09;和 反常游戏 巴什博弈(Bash Game) 一共有n颗石子&#xff0c;两个人轮流拿&#xff0c;每次可以拿1~m颗…...

ES6语法

一、Let、const、var变量定义 1.let 声明的变量有严格局部作用域 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…...

窥探QCC518x-308x系列与手机之间的蓝牙HCI记录与分析 - 耳机篇

上一篇是介绍如何窥探手机端Bluetooth的HCI log, 本次介绍是如何窥探Bluetooth的HCI log-耳机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 Ultra. QCC518x/QCC308x透过HCI界面取得Log教学. 步骤1: 开启QMDE -> 选择ADK r1102 QCC3083 Headset workspace.步骤2: 点…...

ubuntu k8s 1.31

ubuntu 系统 设置 更新源 apt-get upgradeapt upgradeapt update apt-get update释放root sudo passwd root密码su - 密码设置root可以登录 cd /etc/ssh/sshd_config.d && vi ssh.confPermitRootLogin yes PasswordAuthentication yes:wq 保存退出 systemctl resta…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...