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

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

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

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

前言

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

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

相关文章:

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

请直接看原文:设计模式系列 ------------------------------------------------------------------------------------------------------------------------------- 前言 建议在阅读本文前先阅读设计模式(十一)策略模式这篇文章,虽说状态…...

Java基于SpringBoot的在线文档管理系统的设计与实现论文

摘 要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,在线文档管理当然也不能排除在外。在线文档管理系统是以实际运用为开发背景,运用软件工程原理和开发方法&am…...

突破编程_C++_STL教程( list 的高级特性)

1 std::list 的排序 1.1 基础类型以及 std::string 类型的排序 std::list的排序可以通过调用其成员函数sort()来实现。sort()函数使用默认的比较操作符&#xff08;<&#xff09;对std::list中的元素进行排序。这意味着&#xff0c;如果元素类型定义了<操作符&#xff…...

Scratch 第十六课-弹珠台游戏

第十六课-弹珠台游戏 大家好&#xff0c;今天我们一起做一款弹珠台scratch游戏&#xff0c;我们也可以叫它弹球游戏&#xff01;这款游戏在刚出来的时候非常火爆。小朋友们要认真学习下&#xff01; 这节课的学习目标 物体碰撞如何处理转向问题。复习键盘对角色的控制方式。…...

对简单工厂模式、工厂方法模式的思考

目录 1 背景1.1 题目描述1.2 输入描述1.3 输出描述1.4 输入示例1.5 输出示例 2 简单工厂模式3 工厂方法模式4 思考4.1 改进工厂方法模式 1 背景 题目源自&#xff1a;【设计模式专题之工厂方法模式】2.积木工厂 1.1 题目描述 小明家有两个工厂&#xff0c;一个用于生产圆形积木…...

【详识JAVA语言】面向对象程序三大特性之二:继承

继承 为什么需要继承 Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是 现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程序是就需要考虑。 比如&…...

【剑指offer--C/C++】JZ3 数组中重复的数字

一、题目 二、本人思路及代码 这道题目它要求的时间空间利用率都是n&#xff0c;那么可以考虑创建一个长度为n的数组repeat初始化为0&#xff0c;下标代码出现的数字&#xff0c;下标对应的数组内容代表该下标数字出现的次数。然后遍历提供的数组&#xff0c;每出现一个数字&a…...

基于SpringBoot的在线拍卖系统设计与实现(源码)

项目源码&#xff1a;https://gitee.com/oklongmm/biye2 引言 随着互联网技术的发展&#xff0c;电子商务得以快速发展&#xff0c;其中之一的在线拍卖系统也逐渐得到了广泛的应用。但是&#xff0c;现有的在线拍卖系统在操作复杂性、安全性和稳定性方面存在一定的问题。为了…...

卢森堡比利时土耳其媒体宣发稿助力跨境出海推广新闻营销

【本篇由言同数字科技有限公司原创】随着全球化进程的加速&#xff0c;越来越多的品牌开始考虑在海外市场扩展业务。对于品牌来说&#xff0c;跨境海外推广是必要的&#xff0c;因为它可以帮助品牌打开更大的市场、吸引更多的消费者、提高品牌知名度和形象&#xff0c;并在全球…...

冒泡排序(C语言详解)

原理&#xff1a;从左到右一次比较&#xff0c;如果左侧数字比右侧数字大&#xff08;小&#xff09;&#xff0c;则两数交换&#xff0c;否则比较下一 组数字&#xff0c;每一次大循环比较可以将乱序的最右侧数字改为最大&#xff08;最小&#xff09;&#xff0c…...

STC-ISP原厂代码研究之 V3.7d汇编版本

最近在研究STC的ISP程序,用来做一个上位机烧录软件,逆向了上位机软件,有些地方始终没看明白,因此尝试读取它的ISP代码,但是没有读取成功。应该是目前的芯片架构已经将引导代码放入在了单独的存储块中,而这存储块有硬件级的使能线,在面包板社区-宏晶STC单片机的ISP的BIN文…...

【word】引用文献如何标注右上角

一、在Word文档中引用文献并标注在右上角的具体步骤如下 1、将光标移动到需要添加文献标注的位置&#xff1a; 2、在文档上方的工具栏中选择“引用”选项&#xff1a; 3、点击“插入脚注”或“插入尾注”&#xff1a; ①如果选择的是脚注&#xff0c;则脚注区域会出现在本页的…...

MySQL 5.5、5.6、5.7的主从复制改进

主从复制面临的问题 MySQL一直以来的主从复制都是被诟病,原因是: 1、主从复制效率低 早期mysql的复制是通过将binlog语句异步推送到从库。从库启动一个IO线程将接收到的数据记录到relaylog中;另外启动一个SQL线程负责顺序执行relaylog中的语句实现对数据的拷贝。 这里的…...

性能分析排查思路之日志(1)

本文是性能问题分析排查思路的展开内容之一&#xff0c;主要分为日志1期&#xff0c;机器4期、环境2期共7篇系列文章&#xff0c;本期是第一篇&#xff0c;讲日志的分析方法和经验。 系列文章传送门&#xff1a; 一图梳理性能问题分析排查思路-总体概述&#xff08;0&#xff…...

Vue中如何实现条件渲染?

在Vue中实现条件渲染非常简单且灵活&#xff0c;主要通过Vue的指令来实现。在Vue中&#xff0c;我们可以使用v-if和v-else指令来根据条件来渲染不同的内容。下面就让我们通过一个简单的示例来演示如何在Vue中实现条件渲染&#xff1a; <!DOCTYPE html> <html lang&qu…...

Postman上传文件的操作方法

前言 调用某个接口&#xff0c;测试上传文件功能。一时间不知如何上传文件&#xff0c;本文做个操作记录&#xff0c;期望与你有益。 步骤一、设置Headers key:Content-Type value:multipart/form-data 步骤二、设置Body 选择form-data key:file下拉框选择file类型value&…...

linux系统Jenkins工具介绍

Jenkins概念介绍 Jenkins概念Jenkins目的特性产品发布流程 Jenkins概念 Jenkins是一个功能强大的应用程序&#xff0c;允许持续集成和持续交付项目&#xff0c;无论用的是什么平台。这是一个免费的源代码&#xff0c;可以处理任何类型的构建或持续集成。集成Jenkins可以用于一些…...

【python】遵守 robots.txt 规则的数据爬虫程序

程序1 编写一个遵守 robots.txt 规则的数据爬虫程序涉及到多个步骤&#xff0c;包括请求网页、解析 robots.txt 文件、扫描网页内容、存储数据以及处理异常。由于编程语言众多&#xff0c;且每种语言编写爬虫程序的方式可能有所不同&#xff0c;以下将使用 Python 语言举例&am…...

使用爬虫去获取四六级成绩

使用爬虫去获取四六级成绩 今天出成绩&#xff0c;没过&#xff0c;二战六级依然惨死&#xff0c;那么我就写一个简单的爬虫&#xff0c;其实也可以封装成一个接口的&#xff0c;然后直接输入姓名 身份证好 以及四六级即可获取成绩&#xff0c;我就是简单的玩了一下哈&#xf…...

洛谷P1256 显示图像

广搜练手题 题目链接 思路 打印每个数与其最近的 1 1 1的曼哈顿距离&#xff0c;显然广搜&#xff0c;存储每一个 1 1 1&#xff0c;针对每一个 1 1 1开始广搜&#xff0c;逐层更新&#xff0c;每轮后更新的为两轮之中的最小曼哈顿距离 ACcode #include<bits/stdc.h>…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...