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

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

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

前言

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

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 {
    @Override
    public void powerOn() {
        System.out.println("已开机");
    }
    @Override
    public void powerOff() {
        System.out.println("关机");
    }
    @Override
    public void preSong() {
        System.out.println("上一首歌");
    }
    @Override
    public void nextSong() {
        System.out.println("下一首歌");
    }
}

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

public class PowerOffState implements Mp3State {
    @Override
    public void powerOn() {
        System.out.println("开机");
    }
    @Override
    public void powerOff() {
    }
    @Override
    public void preSong() {
    }
    @Override
    public 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.mfbz.cn/a/426822.html

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

相关文章

猴子吃桃问题(python版)

文章预览: 题目python解法一:运行结果 python解法二:运行结果 python解法三:运行结果 题目 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。 第二天早…

基于springboot实现计算机类考研交流平台系统项目【项目源码+论文说明】

基于springboot实现计算机类考研交流平台系统演示 摘要 高校的大学生考研是继高校的高等教育更上一层的表现形式,教育的发展是我们社会的根本,那么信息技术的发展又是改变我们生活的重要因素,生活当中各种各样的场景都存在着信息技术的发展。…

【QT】C/C++ 文件属性设置(隐藏、只读、加密等)方法和程序示例

目录 1文件属性设置 1.1 GetFileAttributes 获取文件属性函数的返回值 1.2 SetFileAttributes 设置文件属性函数 2 文件属性设置示例 1文件属性设置 在MSDN中,文件总共有15种属性,根据磁盘的分区格式不同,文件的属性也会不同。 需要包含头…

buildadmin 入口文件index.php的代码解析

buildadmin的入口文件和一般的tp8的入口文件是不一样的,参考这个入口文件的写法,我们可以大至了解, 为什么,前端的 index.html 和 php的入口文件同在 public 的目录下,而可以不冲突 先看一下 buildadmin的入口文件 &l…

机器学习周报第31周

目录 一、论文阅读1.1 论文标题1.2 论文摘要1.3 论文背景1.4 提出的系统:MAER1.4.1 基于Asyncio的预处理1.4.2 多模态信号下的情感识别1.4.3 针对情感不匹配情况的自适应融合 一、论文阅读 1.1 论文标题 Beyond superficial emotion recognition: Modality-adapti…

opencv实现图像的融合

实现图像的融合并且输出一张jpg格式的照片。 先显示一个彩色图的照片 然后我以彩色方式读取1.png&#xff0c;以灰度图方式读取3.png这张图片&#xff0c;并且用两个窗口独立地去显示(我后来发现不能把灰度图和彩色图相融合) 然后实现两个融合 #include <opencv2/highgu…

OJ:反转链表

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 思路 思路&#xff1a;直接有一个叫移除链表元素的oj&#xff0c;我们在那里因为不想再原链表上修改节点指向&#xff0c;那这个题我们能不能用那个思路呢&#xff0c;其实想一想先拷贝再改变&#xff0c;也挺麻烦的。所…

MySQL 使用 pt-archiver 删除数据

文章目录 前言1. 环境准备1.1 模拟造数1.2 工具安装 2. 删除数据2.1 批次删除表2.2 原理解析2.3 批处理思路 后记 前言 在线核心业务都会有日志表&#xff0c;随着业务持续运行&#xff0c;日志表每天都在增大&#xff0c;最后超过阈值触发空间使用率告警。DBA 处理空间告警时…

Vue开发实例(十一)用户列表的实现与操作

用户列表的实现与操作 一、创建用户页面和路由二、表格优化1、表头自定义2、表格滚动3、加入数据索引4、利用插槽自定义显示 三、功能1、查询功能3、增加4、删除5、修改 一、创建用户页面和路由 创建用户页面 在 src/components/Main 下创建文件夹user&#xff0c;创建文件Us…

java spring 02. AbstractApplicationContext

spring创建对象的顺序&#xff0c;先创建beanfactory&#xff0c;再会把xml文件读取到spring。 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, Nullable ApplicationContext parent)throws BeansException {//调用父类的构造方法super(p…

Django Web架构:全面掌握Django模型字段(上)

Django Web架构 全面掌握Django模型字段&#xff08;上&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article…

【机器人最短路径规划问题(栅格地图)】基于蚁群算法求解

代码获取方式&#xff1a;QQ&#xff1a;491052175 或者 私聊博主获取 基于蚁群算法求解机器人最短路径规划问题的仿真结果 仿真结果 收敛曲线变化趋势 蚁群算法求解最优解的机器人运动路径 各代蚂蚁求解机器人最短路径的运动轨迹

二、TensorFlow结构分析(1)

目录 1、TF数据流图 1.1 TensorFlow结构分析 1.2 案例 2、图与TensorBoard 2.1 图结构 2.2 图相关操作 2.2.1 默认图 2.2.2 创建图 2.3 TensorBoard&#xff1a;可视化学习 2.3.1 数据序列化 - events文件 2.3.2 启动TensorBoard 2.4 OP 2.4.1 常见OP 2.4.2 指令…

20.图

图的基本概念 1.图的定义 由顶点和边组成的集合&#xff0c;G(V,E) 2.基本概念 邻接点&#xff1a; 对于无向图u v来说&#xff0c;uv互为邻接点 对于有向图u->v来说&#xff0c;v是u的邻接点&#xff0c;但u不是v的临界点 路径&#xff1a; 一个顶点到另一个顶点所经过的…

【漏洞复现】通天星CMSV6车载监控平台getImage任意文件读取漏洞

Nx01 产品简介 深圳市通天星科技有限公司&#xff0c;是一家以从事计算机、通信和其他电子设备制造业为主的企业。通天星车载视频监控平台软件拥有多种语言版本。应用于公交车车载视频监控、校车车载视频监控、大巴车车载视频监控、物流车载监控、油品运输车载监控、警车车载视…

【数据结构】_包装类与泛型

目录 1. 包装类 1.1 基本数据类型和对应的包装类 1.2 &#xff08;自动&#xff09;装箱和&#xff08;自动&#xff09;拆箱 1.2.1 装箱与拆箱 1.2.2 自动&#xff08;显式&#xff09;装箱与自动&#xff08;显式&#xff09;拆箱 1.3 valueOf()方法 2. 泛型类 2.1 泛…

bert 相似度任务训练完整版

任务 之前写了一个相似度任务的版本&#xff1a;bert 相似度任务训练简单版本,faiss 寻找相似 topk-CSDN博客 相似度用的是 0&#xff0c;1&#xff0c;相当于分类任务&#xff0c;现在我们相似度有评分&#xff0c;不再是 0,1 了&#xff0c;分数为 0-5&#xff0c;数字越大…

ChatGPT最新功能“Text To Speech (TTS,文本转语音)”详细解读!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

Windows环境MySQL全量备份+增量备份

一、环境准备 1.1.安装MySQL 在进行MySQL数据库备份和还原操作时&#xff0c;必须先提前安装好MySQL环境&#xff0c;且MySQL服务已成功开启 如果没有安装MySQL环境&#xff0c;可以参考博客&#xff1a;http://t.csdnimg.cn/h8bHl 如果已成功安装MySQL环境&#xff0c;打开…

Orbit 使用指南 02 | 在场景中生成原始对象| Isaac Sim | Omniverse

如是我闻&#xff1a; Orbit使用指南02将 深入探讨如何使用Python代码在Orbit中向场景生成各种对象&#xff08;或原始对象&#xff09;。一起探索如何生成地面平面、灯光、基本图形形状以及来自USD文件的网格。前置知识&#xff1a;如何生成空白场景&#xff0c;Orbit 使用指…