设计模式行为型——状态模式

 

目录

状态模式的定义

状态模式的实现

状态模式角色

状态模式类图

状态模式举例

状态模式代码实现

状态模式的特点

优点

缺点

使用场景

注意事项

实际应用


       在软件开发过程中,应用程序中的部分对象可能会根据不同的情况做出不同的行为,把这种对象称为有状态的对象,而把影响对象行为的一个或多个动态变化的属性称为状态。当有状态的对象与外部事件产生互动时,其内部状态就会发生改变,从而使其行为也发生改变。如天气都有晴天和雨天的时候,不同的天气有不同的行为,当然天气也会受影响其他影响变化。

状态模式的定义

        状态模式(State Pattern)属于行为型设计模式,也叫作状态机模式(StateMachine Pattern),对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

        状态模式中类的行为是由状态决定的,在不同的状态下有不同的行为。其意图是让一个对象在其内部改变的时候,行为也随之改变。状态模式的核心是状态与行为绑定,不同的状态对应不同的行为。

        在状态模式中,创建表示各种状态的对象和一个行为随着状态对象改变而改变的context对象。

        状态模式的解决思想是:当控制一个对象状态转换的条件表达式过于复杂时,把相关“判断逻辑”提取出来,用各个不同的类进行表示,系统处于哪种情况,直接使用相应的状态类对象进行处理,这样能把原来复杂的逻辑判断简单化,消除了 if-else、switch-case 等冗余语句,代码更有层次性,并且具备良好的扩展力。

状态模式的实现

状态模式角色

  1. 环境类角色(Context):也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
  2. 抽象状态角色(State):定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
  3. 具体状态角色(Concrete State):实现抽象状态所对应的行为,每一个类封装了一个状态对应的行为,并且在需要的情况下进行状态切换。

状态模式类图

状态模式举例

        打篮球的时候运动员可以有正常状态,不正常状态,和超常状态,现在就以我们打篮球时候投篮时候的状态来举例子。正常状态下运动员投十个球进五个球;不正常状态下运动员投十个球进一个球,和超常状态下运动员投十个球进十个球。此时投篮状态为抽象状态角色,运动员的三种投篮竞技状态为具体状态角色,而运动员为环境类角色。

状态模式代码实现

抽象状态角色

package com.common.demo.pattern.state;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 抽象状态角色 投篮
 * @date 2023/08/07 20:56:20
 */
public interface State {
    /**
     * 投篮
     */
    void shot();
}

具体状态角色

package com.common.demo.pattern.state;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体状态角色 投篮正常
 * @date 2023/08/07 21:00:07
 */
public class NormalState implements State{
    @Override
    public void shot() {
        System.out.println("发挥正常,十中五");
    }
}
package com.common.demo.pattern.state;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体状态角色 投篮超常
 * @date 2023/08/07 21:00:44
 */
public class SuperState implements State{
    @Override
    public void shot() {
        System.out.println("发挥超长,十中十");
    }
}
package com.common.demo.pattern.state;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体状态角色 投篮不正常
 * @date 2023/08/07 20:57:46
 */
public class UnnormalState implements State{
    @Override
    public void shot() {
        System.out.println("投篮发挥失常,十中一");
    }
}

环境类角色

package com.common.demo.pattern.state;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 环境角色 运动员
 * @date 2023/08/07 21:01:45
 */
public class Player {
    private State state = new NormalState();

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

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

测试类

package com.common.demo.pattern.state;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 状态模式测试类
 * @date 2023/08/07 21:02:30
 */
public class StateTest {

    public static void main(String[] args) {
        Player player = new Player();
        player.shot();//正常下投篮
        player.setState(new UnnormalState());
        player.shot();//不正常下投篮
        player.setState(new SuperState());
        player.shot();//超常下投篮
    }
}

测试截图

状态模式的特点

优点

  1. 将状态相关的行为封装到具体状态类中:状态模式通过将不同状态的行为封装到具体状态类中,使得状态之间的转换和行为的变化清晰明确。
  2. 遵循开闭原则:新增状态时无需修改原有代码,只需要添加新的状态类和相应的转换逻辑。
  3. 简化了条件判断:状态模式避免了大量的条件判断语句,使得代码更加可读、可维护。
  4. 符合单一职责原则:将特定的状态及其行为都封装到单独的类中。

缺点

  1. 增加了类的数量:使用状态模式会增加多个具体状态类,导致类的数量增加。
  2. 可能造成状态转换的复杂性:如果状态之间的转换逻辑比较复杂,可能会导致状态转换的控制逻辑变得复杂难以维护。
  3. 状态模式对"开闭原则"的支持并不太好:对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

使用场景

  1. 当对象的行为取决于其内部状态,并且在运行时可以动态改变状态时,可以使用状态模式。
  2. 当对象有多个状态且每个状态对应的行为有所不同时,可以使用状态模式。
  3. 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时,可以使用状态模式。

注意事项

  1. 状态之间的转换关系要清晰:确保状态之间的转换关系清晰明确,避免状态转换的混乱和错误。
  2. 借助上下文对象管理状态:状态模式通常需要配合上下文对象来管理状态的转换和行为委托,确保状态的正确切换和行为的正确执行。
  3. 状态最好不要超过5个:在行为受到状态约束的时候,使用状态模式,且状态最好不要超过5个

实际应用

  1. 订单状态管理:订单的生命周期包含多个状态(待支付、已支付、已发货等),可以使用状态模式来管理订单状态的转换和相应的行为。
  2. 状态机:状态机是一种广泛应用于计算机编程中的模型。状态模式可以用于实现复杂的状态机逻辑。
  3. 游戏角色状态:游戏中的角色可以根据不同的状态进行不同的行为,状态模式可以用于管理角色的状态和行为。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows环境下打印机无法打印的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

勘探开发人工智能技术:机器学习(1)

0 提纲 2.1 什么是机器学习 2.2 不确定性 2.3 数据类型 2.4 分类、回归、聚类 2.5 分类问题的训练与测试 2.6 性能评价指标 1 什么是机器学习 对于西瓜这个抽象类来说,它具有“色泽”,“根蒂”,“敲声”三个属性: 通过观察这个…

[SpringBoot3]基础篇

二、SpringBoot基础篇 2.1什么是SpringBoot SpringBoot是目前流行的微服务框架,倡导“约定优于配置”,其目的是用来简化新Spring应用的初始化搭建以及开发过程。SpringBoot提供了很多核心的功能,比如自动化配置starter(启动器&a…

微服务与Nacos概述-2

微服务间消息传递 微服务是一种软件开发架构,它将一个大型应用程序拆分为一系列小型、独立的服务。每个服务都可以独立开发、部署和扩展,并通过轻量级的通信机制进行交互。 应用开发 common模块中包含服务提供者和服务消费者共享的内容 provider模块是…

Ansible的安装和配置

安装和配置 Ansible 安装所需的软件包 创建名为 /home/greg/ansible/inventory 的静态清单文件,以满足以下要求: 172.25.250.9 是 dev 主机组的成员 172.25.250.10 是 test 主机组的成员 172.25.250.11 和 172.25.250.12 是 prod 主机组的成员 172.2…

闭环控制方法及其应用:优缺点、场景和未来发展

闭环控制是一种基本的控制方法,它通过对系统输出与期望值之间的误差进行反馈,从而调整系统输入,使系统输出更加接近期望值。闭环控制的主要目标是提高系统的稳定性、精确性和鲁棒性。在实际应用中,闭环控制有多种方法,…

深入浅出:MyBatis的使用方法及最佳实践

这里写目录标题 添加MyBatis框架⽀持配置连接字符串和MyBatis配置连接字符串配置 MyBatis 中的 XML 路径 添加业务代码创建数据库和表添加用户实体类添加 mapper 接⼝添加 UserMapper.xml添加 Service层添加 Controller层 增删改操作增加操作删除操作修改操作 添加MyBatis框架⽀…

无感部署 - 蓝绿部署、AB测试、灰度发布

蓝绿部署 蓝绿部署(Blue-Green Deployment)是一种软件发布和部署的策略,旨在实现无缝的应用程序升级和回滚。在蓝绿部署中,同时存在两个环境:一个是当前稳定的生产环境(蓝色环境),另…

Spring Cloud 智慧工地源码(PC端+移动端)项目平台、监管平台、大数据平台

智慧工地源码 智慧工地云平台源码 智慧建筑源码 “智慧工地”是利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术,彻底改变传统建筑施工现场参建各方现场管理的交互方式、工作方式和管理模式,实现对人、机、料、法、环的全方位实时监…

国产航顺HK32F030M: 基于NTC负温度系数的温度计

前言: 家里的一个儿童澡盆附带的温度计坏掉了,拆解后发现这东西做的真垃圾!索性自己做一个。拆下了里面的NTC热敏电阻,但是不知道NTC的性能参数,经过测量与查资料后,采用用中位值滤波 、 Steinhart-Hart方…

swagger 3.0 学习笔记

引入pom <dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency>配置 import io.swagger.models.auth.In; import io.swagger.v3.oas.annotati…

三级城市展示省市区树

展示效果 数据库展示 业务代码 /*** 省市区树*/VLicenseApiOperation("查询经纬度")ApiImplicitParam(name "FnCity", value "省市区树", dataType "FnCity")GetMapping("/districtlist")public AjaxResult districtlist…

strlen和sizeof的区别

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C语言中的sizeof和strlen&#xff08;仅此一篇让你明白它们两的差别&#xff09;&#xff0c;如果大家觉得我写的不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 文章目录 strlensizeof 在…

Simulink仿真模块 -Scope

Scope模块的作用是显示仿真过程中生成的信号。它包含在以下库中: 库: Simulink / Commonly Used BlocksSimulink / SinksHDL Coder / Commonly Used BlocksHDL Coder / Sinks 如图所示: Simulink Scope 模块和 DSP System Toolbox™ Time Scope 模块显示时域信号。…

【APITable】教程:创建并运行一个自建小程序

1.进入APITable&#xff0c;在想要创建小程序的看板页面点击右上角的【小程序】&#xff0c;进入小程序编辑页面。 2.创建一个新的小程序区。 点击【 添加小程序】 点击创建小程序&#xff0c;选择模板&#xff0c;输入名字。 3.确定后进入小程序部署引导页面。 4.打开Xshell 7…

春秋云镜 CVE-2022-0410

春秋云镜 CVE-2022-0410 WordPress plugin The WP Visitor Statistics SQLI 靶标介绍 WordPress plugin The WP Visitor Statistics (Real Time Traffic) 5.6 之前存在SQL注入漏洞&#xff0c;该漏洞源于 refUrlDetails AJAX 不会清理和转义 id 参数。 登陆账户&#xff1a;u…

LeetCode 热题 100 JavaScript -- 74. 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非递减顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 …

D* 算法完全解析(应该是全网最详细的吧)

花了几天时间学习了下 D* 算法&#xff0c;只能说熟悉了一下流程&#xff0c;远不能说掌握&#xff0c;算法实在是非常巧妙 参考 《制造车间无人搬运系统调度方法研究》 《基于D*Lite算法的移动机器人路径规划研究》 人工智能: 自动寻路算法实现(四、D、D*算法) D* 算法 D*路径…

java 文件/文件夹复制,添加压缩zip

复制文件夹,并压缩成zip 需求&#xff1a;创建A文件夹&#xff0c;把B文件夹复制到A文件夹。然后把A文件夹压缩成zip包 public static void main(String[] args) throws Exception {try {String A "D:\\dev\\program";String B "D:\\program";// 创建临…

iOS- git对单个或者多个文件权限设置,使用pre-commit hook 和shell脚本,拦截校验

前提&#xff1a;最近&#xff0c;由于团队代码规范和安全问题&#xff0c;有一些文件只能是指定用户才能修改。 对比&#xff1a;调查了一下资料&#xff0c;发现好多人都在使用pre-commit技术。于是&#xff0c;就朝着这个方向去研究。于是抽空写了脚本&#xff0c;在提交的…