二十三种设计模式第二十三篇--状态模式

news2024/9/23 9:33:50

状态模式,是一种行为模式,在软件开发过程中,对象按照不同的情况做出不同的行为,我们把这样的对象称为具有状态的对象,而把影响对象行为的一个或者多个动态变化的属性称为状态。

对这种具有状态的对象变成,传统的解决方案是,将这些所有可能发生情况全部考虑到,然后使用if-else或者switch-case语句来做状态判断,再进行不同情况的处理。但是这种情况存在一个弊端,就是,条件判断语句会过于浮肿,可读性差,并且不具备拓展性,维护难度也将加大,并且增加新的状态时需要添加新的if-else语句,这违背了“开闭原则”,并不利于程序的拓展。

状态模式:它允许对象在内部状态改变时改变其行为。状态模式将状态和对应的行为封装成不同的状态对象,使得对象的行为可以根据不同的状态进行动态切换。

状态模式的核心组成部分包括:

状态接口(State Interface):定义了状态对象的接口,包含了对象在该状态下可以执行的方法。

具体状态类(Concrete State):实现了状态接口,在具体的状态下定义了对象的行为。

环境类(Context):包含了一个状态对象,并维护当前的状态,可以根据不同的状态调用相应的方法。

状态模式的主要优点包括:

将状态和行为分离:将不同的状态封装成不同的对象,使得状态和行为可以独立变化,提高了代码的灵活性和可维护性。
简化条件语句:通过状态对象的切换来替代复杂的条件语句,使得代码更加清晰和易懂。
符合开闭原则:增加新的状态类不会修改已有的代码,只需要添加新的状态类和相应的转换规则。

关于状态模式的限制和适用场景:
可能增加对象的数量:每个状态都需要一个对应的状态类,可能会增加对象的数量。
当状态比较少且相对简单时,使用状态模式可能会增加代码的
复杂性。

状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

在这里插入图片描述

/**
 * 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
 */
public interface State {

   //行为动作...
   public void doAction(Context context);

}
/**
 * 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
 * 这里代表游戏玩家开始的状态.
 */
public class StartState implements State {
 
   @Override
   public void doAction(Context context) {
      System.out.println("玩家处理于启动状态,开始相应操作");
      //给上下文对象设定对应的状态对象,然后在 context执行对应的操作
      // 这里避免了使用 if...else 这样的判断语句.
      context.setState(this);
   }
 
   @Override
   public String toString(){
      return "开始状态";
   }
}
/**
 * 环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
 *
 * 状态机
 */
public class Context {
   /**
    *  ******* 状态
    */
   private State state;
 
   public Context(){
      state = null;
   }

   //******状态修改
   public void setState(State state){
      this.state = state;
      //TODO:在这里可以加入 状态修改后的进一步的操作...

      //修改状态  -> 触发事件   -> 消息通知   -> 操作  -> 状态改变.
      //    a   ->  e1       ->    b
      //    b   ->   e2      ->    c


   }
 
   public State getState(){
      return state;
   }
}
public class StatePatternDemo {
   public static void main(String[] args) {

      Context context = new Context();
      //注意比较:  以下状态发生变化时,无须要用  if..else做状态判断.

      //设置状态为开始.
      StartState startState = new StartState();
      startState.doAction(context);
 
      System.out.println(context.getState().toString());

      //修改状态为  stop
      StopState stopState = new StopState();
      stopState.doAction(context);
 
      System.out.println(context.getState().toString());
   }
}
/**
 * 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
 * 停止状态
 */
public class StopState implements State {
 
   @Override
   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      //给上下文对象设定对应的状态对象,然后在 context执行对应的操作
      // 这里避免了使用 if...else 这样的判断语句.
      context.setState(this); 
   }
 
   @Override
   public String toString(){
      return "Stop State";
   }
}

路才刚刚开始走,怎么能半路放弃呢?听我所听,做我想做,梦我想梦,也许几年后我看到这句话会把他删掉,也许他就这么挂在这里,一直挂着。我与众生皆为凡人,无高低贵贱,他擅他长,吾擅吾长,何须羡慕他人等?身在其位,专攻其事,如若不善,辞职跑路!何须压抑与心之久,于己不快哉,长路漫漫有人陪同吾亦乐之,无人陪同吾亦独行,彼岸花开,终有一日,吾亦赏之。

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

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

相关文章

《Java面向对象程序设计》学习笔记——第 1 章 Java入门

专栏:《Java面向对象程序设计》学习笔记

第28天-Kubernetes架构,集群部署,Ingress,项目部署,Dashboard

1.K8S集群部署 1.1.k8s快速入门 1.1.1.简介 Kubernetes简称k8s,是用于自动部署,扩展和管理容器化应用程序的开源系统。 中文官网:https://kubernetes.io/zh/中文社区:https://www.kubernetes.org.cn/官方文档:https…

git管理工具学习(图解使用git工作流程)

目录 GIT 简介一个最简单的GIT操作流程git的工作流程&命令 GIT 简介 git是什么,在维基百科上是这么介绍的:git是一个分布式的版本控制软件 分布式是相对于集中式而言的,分布式即每一个git库都是一个完整的库。 每个库的地位都是平等的&am…

STM32存储左右互搏 I2C总线读写EEPROM ZD24C1MA

STM32存储左右互搏 I2C总线读写EEPROM ZD24C1MA 在较低容量存储领域,EEPROM是常用的存储介质,不同容量的EEPROM的地址对应位数不同,在发送字节的格式上有所区别。EEPROM是非快速访问存储,因为EEPROM按页进行组织,在连…

c 语言解析 时间字符串

#include <iostream> #include <ctime>int main(int argc, char *argv[]) {struct tm timeinfo;char cur_time[] "current time: 2021-09-06 23:50:13";// 解析时间到timeinfo中strptime(cur_time, "current time: %Y-%m-%d %H:%M:%S", &…

数据库管理员知识图谱

初入职场的程序猿&#xff0c;需要为自己做好职业规划&#xff0c;在职场的赛道上&#xff0c;需要保持学习&#xff0c;并不断点亮自己的技能树。  成为一名DBA需要掌握什么技能呢&#xff0c;先让Chat-GPT为我们回答一下&#xff1a; 数据库管理系统 (DBMS)知识&#xff…

加强Web应用程序安全:防止SQL注入

数据库在Web应用程序中存储和组织数据时起着至关重要的作用&#xff0c;它是存储用户信息、内容和其他应用程序数据的中央存储库。而数据库实现了高效的数据检索、操作和管理&#xff0c;使Web应用程序能够向用户提供动态和个性化的内容。然而&#xff0c;数据库和网络应用程序…

微信小程序原生写法传递参数

微信小程序原生写法传递参数 data-xxx 自定义参数名 &#xff0c;接收参数&#xff1a;方法&#xff08;变量名&#xff09; checkVip:function(event) {let that thisconsole.log(event,event)console.log(event.currentTarget.dataset.idx,index)let index Number(eve…

SpringBoot复习:(13)Banner是怎么打印出来的?

SpringApplication的run方法代码&#xff1a; public ConfigurableApplicationContext run(String... args) {long startTime System.nanoTime();DefaultBootstrapContext bootstrapContext createBootstrapContext();ConfigurableApplicationContext context null;configur…

<C++> 三、内存管理

1.C/C内存分布 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";const char *pChar3 "abcd";int *ptr1…

重学C++系列之异常

一、什么是异常 异常一般是指程序运行期发生的非正常情况。异常一般是不可预测的&#xff0c;如&#xff1a;内存不足&#xff0c;打开文件失败&#xff0c;数组越界&#xff0c;范围溢出等。 在某段程序发生无法继续正常执行的情况时&#xff0c;C允许程序进行所谓抛出异常&am…

实现Feed流的三种模式:拉模式、推模式和推拉结合模式

在互联网产品中&#xff0c;Feed流是一种常见的功能&#xff0c;它可以帮助我们实时获取我们关注的用户的最新动态。Feed流的实现有多种模式&#xff0c;包括拉模式、推模式和推拉结合模式。在本文中&#xff0c;我们将详细介绍这三种模式&#xff0c;并通过Java代码示例来实现…

0801|IO进程线程day4(文件IO函数)

作业1&#xff1a;从终端获取一个文件的路径以及名字 若该文件是目录文件&#xff0c;则将该文件下的所有文件的属性显示到终端&#xff0c;类似ls -l该文件夹若该文件不是目录文件&#xff0c;则显示该文件的属性到终端上&#xff0c;类似ls -l这单个文件 以下代码只能跑本目录…

IDEA中修改类头的文档注释信息

IDEA中修改类头的文档注释信息 选择File--Settings--Editor--File and Code Templates--Includes&#xff0c;可以把文档注释写成这种的 /**author: Arbicoralcreate: ${YEAR}-${MONTH}-${DAY} ${TIME}Description: */这样回看就可以很清楚的看到自己创建脚本的时间&#xff…

Vue2 第十三节 使用Vue脚手架(一)

1.初始化脚手架 2.分析脚手架结构 3.修改默认配置 一.初始化脚手架 1.Vue脚手架式Vue官方提供的标准化开发工具 2.具体步骤 ① 如果下载缓慢&#xff0c;需要配置npm淘宝镜像 npm config set registry http://registry.npm.taobao.org ② 全局安装: npm install -g vu…

Jenkins配置流水线

一、新建任务 这个任务名称将会是Jenkins的workspace路径下的一个目录&#xff0c;如我建立了一个test任务&#xff0c;那么Jenkins会生成一个/jenkins_home/workspace/test目录&#xff0c;用来拉取代码编译等。所以请谨慎设置任务名称。

直线模组如何进行精度校准?

直线模组是一种高精度的传动元件&#xff0c;而精度是直线模组的重要指标&#xff0c;在直线模组的使用中&#xff0c;我们应该尽可能的避免直线模组的精度受损&#xff0c;这样才能够有真正的发挥出直线模组的稳定性。 直线模组的精度一般是指重复定位精度和导向精度&#xff…

puppeteer监听response并封装为express服务调用

const express require(express); const puppeteer require(puppeteer); const app express(); let browser; // 声明一个全局变量来存储浏览器实例app.get(/getInfo, async (req, res) > {try {const page_param req.query.page; // 获取名为"page"的查询参数…

汉王人脸考勤管理系统SQL注入RCE

忘掉&#xff01;忘掉温暖&#xff0c;忘掉温柔&#xff0c;忘掉一切享乐&#xff0c;而把饥饿、寒冷、受辱、受苦当做自己的正常生活 漏洞描述 汉王人脸考勤管理系统存在SQL注入漏洞&#xff0c;攻击者可利用该漏洞获取数据库敏感信息并Getshell。 漏洞复现 访问漏洞url&a…

MySQL多版本并发控制

1. 什么是MVCC MVCC(Multiversion Concyrrency Contril)&#xff0c;多版本并发控制。顾名思义&#xff0c;MVCC是通过数据行的多个版本来管理实现数据库的 并发控制。这项技术使得在innodb的事务隔离级别下执行 一致性读 操作有了保证。换言之&#xff0c;就是为了查询一些正在…