设计模式(十五)状态模式

请直接看原文:
设计模式系列

------------------------------------------------------------------------------------------------------------------------------- 

前言

建议在阅读本文前先阅读设计模式(十一)策略模式这篇文章,虽说状态模式和策略模式的结构几乎是相同的,但是它们所解决的问题是不同的,读完这两篇文章你就会有了答案。

1.状态模式定义
状态模式定义

定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

状态模式UML图

在享元模式中有如下角色:

  • Context:环境角色,定义客户端需要的接口,并且负责具体状态的切换。
  • State:抽象状态角色,可以是抽象类或者接口,负责对象状态定义,并封装了环境角色。
  • ConcreteState:具体状态角色,实现抽象角色类,定义了本状态所要做的事情。
2.简单实现状态模式

拿用mp3听歌来说,mp3有四种基本状态,分别是开机、关机、上一首歌和下一首歌。如果我们要写一个对mp3进行控制的类,你可能会这样写,如下所示。

public class Mp3Controller {private static final int POWER_ON = 1;private static final int POWER_OFF = 2;private int state = POWER_OFF;public void powerOn() {if (state == POWER_OFF) {System.out.println("开机");}state = POWER_ON;}public void powerOff() {if (state == POWER_ON) {System.out.println("关机");}state = POWER_OFF;}public void preSong() {if (state == POWER_ON) {System.out.println("上一首歌");}}public void nextSong() {if (state == POWER_ON) {System.out.println("下一首歌");}}
}

在powerOn和powerOff方法中我们会将state置为相应的状态,在preSong和nextSong方法中,首先要判断当前mp3的state,如果是POWER_OFF,则不做任何处理,写到这里你可能会觉得实现很简单啊。那么我再添加些状态,比如待机状态、休眠状态、亮屏状态等等,顺便再添加些功能,比如调大音量、调小音量、降噪等。这样你实现起来,就会发现你会定义很多种状态,在功能中可能要用到多个条件语句进行判断,这会使得代码变得臃肿。
状态模式就是为了解决这一问题,将多个条件语句去掉,使得代码更加清晰,下面来进行实现。

抽象状态角色
public interface Mp3State {//开机public void powerOn();//关机public void powerOff();//上一首歌曲public void preSong();//下一首歌曲public void nextSong();
}

接口Mp3State中定义了四种功能,接下来我们来实现Mp3State。

具体状态角色

我们先来实现开机状态,代码如下所示。

public class PowerOnState implements Mp3State {@Overridepublic void powerOn() {System.out.println("已开机");}@Overridepublic void powerOff() {System.out.println("关机");}@Overridepublic void preSong() {System.out.println("上一首歌");}@Overridepublic void nextSong() {System.out.println("下一首歌");}
}

比较特殊的是powerOn方法中,打印了“已开机”,因为在PowerOnState 状态下进行开机操作是多此一举的。
接着实现关机状态:

public class PowerOffState implements Mp3State {@Overridepublic void powerOn() {System.out.println("开机");}@Overridepublic void powerOff() {}@Overridepublic void preSong() {}@Overridepublic void nextSong() {}
}

在关机状态中只实现了powerOn方法,其他的方法都是空实现。

环境角色
public class Context {private Mp3State mp3State;public void setMp3State(Mp3State mp3State){this.mp3State=mp3State;}public void powerOn(){mp3State.powerOn();setMp3State(new PowerOnState());}public void powerOff(){mp3State.powerOff();setMp3State(new PowerOffState());}public void preSong(){mp3State.preSong();}public void nextSong(){mp3State.nextSong();}
}

Context 中定义了setMp3State方法,用来设定状态,其中powerOn方法中会调用setMp3State方法将状态置为PowerOffState,同理powerOff中将状态置为PowerOffState。

客户端调用
public class Client {public static void main(String[] args){Context context=new Context();context.setMp3State(new PowerOffState());context.preSong();context.powerOn();context.nextSong();context.powerOff();}
}

我们只需要先设定mp3的初始状态,就可以调用各种功能方法了,不需要再考虑功能和状态之间的关系。输出结果为:
开机
下一首歌
关机

虽然这个例子的代码很简单,这里还是给出UML图,如下所示。

3.状态模式的使用场景和优缺点
优点
  • 避免了过多的条件语句,使得结构更清晰,提高代码的可维护性。
  • 每个状态都是一个子类,方便增加和修改状态。
  • 状态被放置到类的内部,外部调用不需要知道类的内部如何实现状态和行为的变换。
缺点
  • 完全使用状态模式,可能会导致子类会过多。
使用场景
  • 代码中包含大量与对象状态有关的条件语句。
  • 对象的行为依赖着状态,并且行为随着状态的改变而改变。

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

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

相关文章

java.sqlrecoverableexception: io error: the network adapter could not establ

数据库相关学习资料下载地址: 数据库相关资料合集 Java SQLRecoverableException: IO Error: The Network Adapter Could Not Establish Connection 在进行Java开发中,经常会遇到与数据库进行交互的情况。然而,有时候我们可能会遇到java.sq…

Redis过期删除策略

1、定时删除: 一旦键过期就立即从内存中删除,节省内存空间,但删除过程会占用大量CPU时间,可能影响服务器的响应时间和吞吐量。 2、惰性删除: 并不会立即从内存中删除过期键,而是在需要访问时才会检查是否…

【MATLAB】MVMD_ MFE_SVM_LSTM 神经网络时序预测算法

有意向获取代码,请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 MVMD_MFE_SVM_LSTM神经网络时序预测算法结合了多变量多尺度分解(MVMD)、多尺度特征提取(MFE)、支持向量机(SVM)和长…

Python爬虫之爬取并下载哔哩哔哩视频

亲自使用过,太好用了 # 导入requests模块,模拟发送请求 import requests # 导入json import json # 导入re import re# 定义请求头 headers {Accept: */*,Accept-Language: en-US,en;q0.5,User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6…

小米消息队列的选型与实践

之前写了一篇关于消息队列的文章:《消息队列介绍与对比》,本文主要介绍消息队列在实际工作中的使用情况(截止到2023年,因为我2023年离职了,后续的情况不了解了,哈哈)。 市面上的多种消息队列都有…

node问题: command not found: nodemon

如何安装并使用 nodemon npm i -g nodemon 问题与解决方案: 问题:zsh: command not found: nodemon 解决方案: 在你的 package.json 中加入: "scripts": {"auto": "npx nodemon server.js" }…

单例模式及应用场景

如果希望自己的代码更优雅、可维护性更高以及更简洁,往往离不开设计模式这一解决方案。 在JS设计模式中,最核心的思想:封装变化(将变与不变分离,确保变化的部分灵活,不变的部分稳定)。 那么来…

[嵌入式系统-36]:龙芯1B 开发学习套件 -5- PMON常见命令

目录 0. 开机时按c键进入pmon模式 (自启动模式时) 1、帮助命令 h 2、显示设备信息 devls 3.重启:reboot 4、设置环境变量 set/unset 5.查询环境变量:env 6.网络设置相关命令: ①设置IP:ifconfig&am…

Linux 基础IO(1)内存文件

文章目录 铺垫文件的系统调用接口文件描述符缓冲区 铺垫 文件文件内容 文件属性访问文件之前,都要先打开文件,而要访问,修改,编辑文件,文件就必须加载到内存中程序运行起来变成进程,被CPU调度,…

详解Win 7重置电脑操作步骤

文章目录 介绍Win 7 重置系统的方法:1.按下键盘上的Windows键和R键,打开运行窗口,输入sysprep 点击回车确定。2.之后就会出现如下界面,在这个新打开的窗口中双击 sysprep 程序3.选择【进入系统全新体验(00BE) 】&#…

基于SpringBoot的在线拍卖系统(附项目源码+论文)

摘要 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单管理、留言板管理、系统管理,用户;首页、个人中心、历史竞拍管理、竞拍订单管理、留言板管理&#xff0…

Linux重新获取IP地址

你可以通过重启客户端来获取新的IP地址。可以使用以下命令来重启DHCP客户端: sudo dhclient -r # 释放当前IP sudo dhclient # 获取新的IP 这将释放当前的IP地址,并请求新的IP地址。 使用ifdown和ifup命令:另一种方法是使用ifdown和i…

STM32学习和实践笔记(1): 装好了的keil μVision 5

2019年3月在淘宝上买了这块STM32的开发板,学了一段时间后就丢下了,今天重新捡起来,决定好好学习、天天向上。 对照教程,今天先把keil5装上了。 装的过程有以下几点值得记录下: 1)用注册机时,…

【应用多元统计分析】--多元数据的直观表示(R语言作图)

例1.2 为了研究全国31个省、市、自治区2018年城镇居民生活消费的分布规律,根据调查资料做区域消费类型划分。 指标: 食品x1:人均食品支出(元/人) 衣着x2:人均衣着商品支出(元/人) 居住x3:人均居住支出(元/人) 生活x4…

欧拉回路(Eulerian Path)

1.定义 如果图 G G G(有向图或者无向图)中所有边一次仅且一次行遍所有顶点的通路称作欧拉通路。 如果图 G G G中所有边一次仅且一次行遍所有顶点的回路称作欧拉回路。 具有欧拉回路的图成为欧拉图(简称 E E E图)。具有欧拉通路但不具有欧拉回路的图成为半欧拉图。 顶点可以经…

【Linux】Linux常用指令介绍

目录 1、whoami命令 2、pwd命令 3、ls命令 4、cd命令 5、touch命令 6、mkdir命令 7、rm命令 8、man命令 9、cp命令 10、mv命令 11、cat命令 12、more命令 13、less命令 14、head命令 15、tail命令 16、find命令 1、whoami命令 语法:whoani 功能&a…

SpringMVC--03--前端传数组给后台

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 案例1乘客个人信息方法1:表单提交,以字段数组接收方法2:表单提交,以BeanListModel接收方法3:将Json对象序…

leetcode移除元素

注意,在本题中,是对原数组进行操作,需要原地删除指定元素,所以我们可以采用快慢指针来操作。 顾名思义,快慢指针是有两个指针,一直快指针,一个慢指针。在本题中,快慢指针起点都是0&a…

解锁人体姿态的秘密:部件亲和场(PAF)的革新应用

部件亲和场(PAF)原理及其在人体姿态估计中的应用 摘要: 随着人工智能技术的发展,人体姿态估计在计算机视觉领域受到越来越多的关注。部件亲和场(Part Affinity Fields,简称PAF)作为一种新兴的人体姿态估计技术,通过构建2D向量场来描述人体肢体的方向和位置信息,从而…

Matlab 机器人工具箱 运动学

文章目录 R.fkine()R.ikine()R.ikine6s()R.ikuncR.jacob0、R.jacobn、R.jacob_dotjtrajctraj参考链接 官网:Robotics Toolbox - Peter Corke R.fkine() 正运动学,根据关节坐标求末端执行器位姿 mdl_puma560; % 加载puma560模型 qz % 零角度 qr …