设计模式——状态模式

news2024/11/19 1:28:43

状态模式

定义

当一个对象内在的状态改变时,允许其改变行为,这个对象看似改变了其类

状态模式的核心是封装,状态的变更引起行为的变更,从外部看来就好像这个对象对应的类发生了变化一样。

优缺点、应用场景

优点

  1. 结构清晰。避免使用switch和if-else来处理每个状态转变到另一个状态的细节
  2. 遵循设计原则。很好地体现了开闭原则和单一职责原则,每个状态作为一个独立类,专注自己的责任。
  3. 封装性好。高层模型不需要了解子类的具体实现,只需要按照暴露出的流程使用即可。

缺点

  1. 子类会太多。对于一个事物来说,状态多就会导致类膨胀,并且不同状态对于事件都有不同的处理方法

应用场景

  1. 行为随状态的改变而改变
  2. 条件、分支判断语句的替代

代码模拟场景

使用电梯时的状态,包括:开门、关门、运行、停止。每种状态向其他状态转变的逻辑都不同。

开门(Open)关门(Close)运行(Run)停止(Stop)
开门状态××
关门状态
运行状态××
停止状态

状态模式

UML图

在这里插入图片描述

状态的抽象和实现

/**
 * 抽象电梯状态
 */
public abstract class LiftState {
	/**
	 * 环境角色
	 */
	protected Context context;

	public void setContext(Context context) {
		this.context = context;
	}

	/**
	 * 开门动作
	 */
	public abstract void open();

	/**
	 * 关门动作
	 */
	public abstract void close();

	/**
	 * 电梯运行
	 */
	public abstract void run();

	/**
	 * 电梯停止
	 */
	public abstract void stop();

}

/**
 * 电梯开门状态
 */
public class OpenState extends LiftState {
	@Override
	public void open() {
		System.out.println("电梯开门...");
	}

	/**
	 * 开门的状态下可以关门
	 */
	@Override
	public void close() {
		// 状态修改
		super.context.setLiftState(Context.CLOSE_STATE);
		// 动作委托CloseState来执行
		super.context.getLiftState().close();
	}

	/**
	 * 不能运行
	 */
	@Override
	public void run() {
	}

	/**
	 * 不能停止
	 */
	@Override
	public void stop() {
	}
}

/**
 * 电梯关门状态
 */
public class CloseState extends LiftState {
	/**
	 * 关门的状态下可以开门
	 */
	@Override
	public void open() {
		super.context.setLiftState(Context.OPEN_STATE);
		super.context.getLiftState().open();
	}


	@Override
	public void close() {
		System.out.println("电梯关门...");
	}

	/**
	 * 门关闭了就可以运行
	 */
	@Override
	public void run() {
		super.context.setLiftState(Context.RUN_STATE);
		super.context.getLiftState().run();
	}

	/**
	 * 关着门不按楼层也可以,就停那了
	 */
	@Override
	public void stop() {
		super.context.setLiftState(Context.STOP_STATE);
		super.context.getLiftState().stop();
	}
}

/**
 * 电梯运行状态
 */
public class RunState extends LiftState {
	/**
	 * 运行中不能开门
	 */
	@Override
	public void open() {
	}

	/**
	 * 门已经关上了
	 */
	@Override
	public void close() {
	}

	@Override
	public void run() {
		System.out.println("电梯正在运行...");
	}

	/**
	 * 到楼层了可以停下
	 */
	@Override
	public void stop() {
		super.context.setLiftState(Context.CLOSE_STATE);
		super.context.getLiftState().stop();
	}
}

/**
 * 电梯关闭状态
 */
public class StopState extends LiftState {
	/**
	 * 停下可以开门
	 */
	@Override
	public void open() {
		super.context.setLiftState(Context.OPEN_STATE);
		super.context.getLiftState().open();
	}

	/**
	 * 停止可以关门
	 */
	@Override
	public void close() {
		super.context.setLiftState(Context.CLOSE_STATE);
		super.context.getLiftState().close();
	}

	/**
	 * 可以再运行起来
	 */
	@Override
	public void run() {
		super.context.setLiftState(Context.RUN_STATE);
		super.context.getLiftState().run();
	}

	@Override
	public void stop() {
		System.out.println("电梯停下了...");
	}
}

上下文对象

/**
 * 上下文对象
 */
public class Context {
	/**
	 * 定义当前电梯的状态
	 */
	private LiftState liftState;
	public static final LiftState OPEN_STATE = new OpenState();
	public static final LiftState CLOSE_STATE = new CloseState();
	public static final LiftState RUN_STATE = new RunState();
	public static final LiftState STOP_STATE = new StopState();

	public void open() {
		this.liftState.open();
	}

	public void close() {
		this.liftState.close();
	}

	public void run() {
		this.liftState.run();
	}

	public void stop() {
		this.liftState.stop();
	}

	public LiftState getLiftState() {
		return liftState;
	}

	public void setLiftState(LiftState liftState) {
		this.liftState = liftState;
		this.liftState.setContext(this);
	}
}

入口类

private static void statePattern() {
	Context context = new Context();
	// 定义电梯初始状态为关闭
	context.setLiftState(Context.CLOSE_STATE);
	context.open();
	context.close();
	context.run();
	context.stop();
}

结果

在这里插入图片描述

参考书籍

秦小波《设计模式之禅》

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

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

相关文章

MiniGPT4系列之三模型推理 (Web UI):在RTX-3090 Ubuntu服务器推理

MiniGPT4系列之一部署篇:在RTX-3090 Ubuntu服务器部署步骤详解_seaside2003的博客-CSDN博客 MiniGPT4系列之二推理篇:在RTX-3090 Ubuntu服务器推理详解_seaside2003的博客-CSDN博客 MiniGPT4系列之三模型推理 (Web UI):在RTX-3090 Ubuntu服…

华为OD机试真题 Java 实现【红黑图】【2023Q1 200分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、补充说明五、解题思路六、Java算法源码七、效果展示1、输入2、输出 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷)》。 刷的越多,抽中的概率越大&…

百度留痕是什么方法排名的

百度留痕是什么方法排名的,黑帽seo教学:谷歌外推搜索留痕关键词秒收录排名软件技术培训 #外推留痕 #黑帽seo #黑帽seo培训 今天给大家看一个百度留痕的一个链接,东西也很简单,其实就是前面的一个地址加后面的一个你的联系方式,你…

三菱plc以太网连接电脑步骤

大家好,今天要和大家分享一个在生产管理系统中的常见问题:如何更方便地上位机访问PLC。我们知道,三菱FX系列PLC好多型号常常不带网口,这给上位机访问带来了不小的麻烦。但是,通过一款名为捷米特JM-ETH-FX的转换器&…

全程干货不愧是Alibaba总结的《Java面试权威指南泰山版》。

随着Java这个行业的兴起,薪资成功的吸引了一大批人,不管是在家待业的、对自己现在工作不满意的、大学选错专业的、缺钱的、想自己学的等等这些人绝大部分都是选择了去学习Java,然后就导致现在培训结构大量的流水线化,带着你走完一…

前端性能优化---样式计算

理论 样式计算 第一步,匹配一系列的样式选择器 第二步,取出所有匹配后的样式规则,构造RenderStyle 步骤 我们的解决思路是 减少样式计算的相互作用,即样式重新计算 什么是 Recalculate Style?在浏览器每一帧的渲染流…

详解c++---c++11(下)

目录标题 default关键字delete关键字lambda表达式为什么会有lambda表达式lambda的用法多线程和lambdalambda的底层 可变参数模板emplace包装器为什么会有包装器包装器的使用 bind default关键字 C11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数&#xff0…

【搜索引擎】提高Apache Solr 性能

这是一个关于我们如何设法克服搜索和相关性堆栈的稳定性和性能问题的简短故事。 语境 在过去的 10 个月里,我很高兴与个性化和相关性团队合作。我们负责根据排名和机器学习向用户提供“个性化和相关的内容”。我们通过一组提供三个公共端点的微服务来做到这一点&…

【docker】它们之间如何通信和阻止,以及容器的基本概念

此篇文章主要是简单讲解,docker之间的通信方式以及和如何阻止docker之间的通信 目录 1、如何docker通信1.1、网络连接1.2、链接(Linking)1.3、共享数据卷(Shared Volumes)1.4、服务发现和负载均衡 2、阻止docker通信2.…

微信公众号搭建内网穿透骨灰级教程

微信公众号是我们日常使用的小工具,很多企业都会去申请微信公众号,但为了及时获取推送消息,需要开发者自己去调用微信公共号接口进行功能扩展和对接, 接下来演示如何使用神卓互联内网穿透服务来生成公网访问地址,以便…

【运维工程师学习五】数据库之MariaDB

【运维工程师学习五】数据库 1、常用的关系型数据库2、C/S结构3、MariaDB图形客户端4、安装MariaDB5、启动MariaDB及验证启动是否成功6、验证启动——端口7、验证启动——进程8、MariaDB配置文件路径主配置文件解读: 9、MariaDB的配置选项10、MariaDB客户端连接1、在…

MWeb Pro for Mac(苹果电脑最好用的Markdown编辑器)安装教程

MWeb Pro是一款专业的Mac平台上的Markdown编辑器,可以帮助用户更加高效地书写和排版文本内容,支持多种文本格式的导入和导出,如HTML、RTF、PDF等,还支持实时预览和代码高亮等功能,为用户提供了非常优秀的Markdown编辑体…

02LINGO基本操作

某公司新购置了某种设备 6 台,欲分配给下属的4 个企业,已知各企业获得这种设备后年创利润如表 1.1 所示,单位为千万元。问应如何分配这些设备能使年创总利润最大,最大利润是多少? 甲乙丙丁1423426455376764788657986671086 甲公…

【Java进阶之路】LinkedList源码分析

概述 LinkedList也是我们经常使用的集合,本文就LinkedList的几个主要方法展开介绍,并结合几个图片来介绍几个重要操作。 基础属性 transient int size 0; //节点数量/*** Pointer to first node.* Invariant: (first null && last null) |…

windows上安装Vmware及Linux系统

Linux系统的安装 一、windows上安装Vmware 第一步:复制VMware软件包到Windows系统中 第二步:双击VMware安装包,进行软件的安装 第三步:勾选软件的许可协议 第四步:设置VMware安装路径以及勾选增强型的键盘程序 第五步…

Three.js环境光,平行光,点光源,聚光灯的创建和灯光辅助线的使用

Three.js中的灯光API使用 1.环境光(AmbientLight)2.平行光(directionalLight)3.PointLight(点光源) 4.聚光灯(SpotLight)5.材质平面(PlaneGeometry)用于接收(平行光和聚…

【边缘计算】【第一章 什么是边缘计算】

边缘计算 序第一章 什么是边缘计算概念章鱼说应用场景数据单位转换边缘计算的前世今生CDN(Content Delivery Network)内容分发网络微云(Cloudlet)雾计算——雾是接近地面的云MEC边缘计算大事记 边缘计算核心技术概述1 网络技术2 隔…

explain 是干嘛的

explain 是干嘛的 1.explain的作用 在MySQL中,EXPLAIN是一个用于查询优化的关键字。它可以用于分析查询语句的执行计划,帮助开发人员和数据库管理员理解查询的执行方式、查询涉及的表和索引、连接类型、查询优化器的决策等信息。 通过使用EXPLAIN关键…

智慧团建登录或忘记密码刷不出验证码

问题如下: 忘记密码和登录时没有验证码 原因:智慧团建的服务器端只放行不带“www.”的域名,一般zf或者其他jg系统都会限制万维网的进入 解决办法: 删掉“www.”,然后重新回车访问或者直接点我下边的链接:…

PyTorch翻译官网教程6-AUTOMATIC DIFFERENTIATION WITH TORCH.AUTOGRAD

官网链接 Automatic Differentiation with torch.autograd — PyTorch Tutorials 2.0.1cu117 documentation 使用TORCH.AUTOGRAD 自动微分 当训练神经网络时,最常用的算法是方向传播算法。在该算法中,根据损失函数与给定参数的梯度来调整模型参数&…