设计模式-第13章(状态模式)
状态模式
- 状态模式
- 状态模式的好处和用处
- 工作状态
状态模式
状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

State类,抽象状态类,定义一个接口以封装与 Context 的一个特定状态相关的行为。
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
抽象状态类
abstract class State {public abstract void handle(Context context);
}
具体状态类
//具体状态类A
class ConcreteStateA extends State
{public void handle(Context context) {// 处理并设置新的状态context.setState(new ConcreteStateB());}
}
//具体状态类B
class ConcreteStateB extends State
{public void handle(Context context) {// 处理并设置新的状态context.setState(new ConcreteStateA());}
}
Context类
// 上下文
class Context {// 包含一个状态private State state;public Context(State state){this.state = state;}//可读写的状态属性,用于读取当前状态和设置新状态public State getState(){return this.state;}public void setState(State value){this.state = value;System.out.println("当前状态:" + this.state.getClass().getName());}public void request(){// 对请求进行处理,并设置下一个状态this.state.handle(this); }
}
客户端
public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大话设计模式》代码样例");System.out.println();// 新建一个context实例,并设置一个状态 Context c = new Context(new ConcreteStateA());// 根据状态,对请求做出不同的行为,处理完成后,进行状态转换。c.request();c.request();c.request();c.request();System.out.println();System.out.println("**********************************************");}
}
在上面的Context类中,包含了一个状态对象,Context在根据不同的状态去执行不同的行为,在具体状态类中,在处理完成请求后,又改变了Context类中的状态。不断的请求,不断的改变状态。
状态模式的好处和用处
状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来,每一个状态对应了一个状态类。
将特定的状态相关的行为都放在一个对象中,由于每一种状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
这样做的目的就是消除庞大的判断状态的条件分支语句,状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
何时考虑使用状态模式?
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
工作状态
根据不同的时间段,工作的状态不同。针对每一个状态,定义不同的行为。把每一个状态相关的行为都定义在同一个对象中。在抽象状态类中有一个 写程序的行为,在状态子类中,根据状态给出不同的实现。在状态子类中,根据条件完成状态的转换。

抽象状态类
abstract class State {// 定义每一个状态中所需要实现的行为public abstract void writeProgram(Work w);
}
具体的状态类
//上午工作状态
class ForenoonState extends State {public void writeProgram (Work w) {// 根据时间来判断,状态的转换if (w.getHour() < 12) {System.out.println("当前时间:"+ w.getHour() +"点 上午工作,精神百倍");}else {w.setState(new NoonState());w.writeProgram();}}
}
//中午工作状态
class NoonState extends State {public void writeProgram (Work w) {if (w.getHour() < 13) {System.out.println("当前时间:"+ w.getHour() +"点 饿了,午饭;犯困,午休。");}else {// 设置新的状态w.setState(new AfternoonState());w.writeProgram();}}
}
//下午工作状态
class AfternoonState extends State {public void writeProgram (Work w) {if (w.getHour() < 17) {System.out.println("当前时间:"+ w.getHour() +"点 下午状态还不错,继续努力");}else {// 设置新的状态w.setState(new EveningState());w.writeProgram();}}
}//晚间工作状态
class EveningState extends State {public void writeProgram(Work w){ // 晚上 17点后,根据工作完成的属性,进行状态的转换if (w.getWorkFinished()) { // 设置新的状态w.setState(new RestState());w.writeProgram();}else{if (w.getHour() < 21) {System.out.println("当前时间:"+ w.getHour() +"点 加班哦,疲累之极");}else {w.setState(new SleepingState());w.writeProgram();}}}
}
//睡眠状态
class SleepingState extends State {public void writeProgram(Work w) {System.out.println("当前时间:"+ w.getHour() +"点 不行了,睡着了。");}
}
//下班休息状态
class RestState extends State {public void writeProgram(Work w) {System.out.println("当前时间:"+ w.getHour() +"点 下班回家了");}
}
工作类
class Work {// 当前的状态private State current;public Work(){current = new ForenoonState(); }//设置状态public void setState(State value) {this.current = value;}//写代码的状态public void writeProgram() {this.current.writeProgram(this);}//当前的钟点,根据时间,进行状态的转换private int hour;public int getHour(){return this.hour;}public void setHour(int value){this.hour = value;}//当前工作是否完成// 根据工作是否完成来进行状态的转换private boolean workFinished = false;public boolean getWorkFinished(){return this.workFinished;}public void setWorkFinished(boolean value){this.workFinished = value;}
}
客户端
public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大话设计模式》代码样例");System.out.println(); //紧急项目Work emergencyProjects = new Work();emergencyProjects.setHour(9);emergencyProjects.writeProgram();emergencyProjects.setHour(10);emergencyProjects.writeProgram();emergencyProjects.setHour(12);emergencyProjects.writeProgram();emergencyProjects.setHour(13);emergencyProjects.writeProgram();emergencyProjects.setHour(14);emergencyProjects.writeProgram();emergencyProjects.setHour(17);emergencyProjects.setWorkFinished(false);//emergencyProjects.setWorkFinished(true);emergencyProjects.writeProgram();emergencyProjects.setHour(19);emergencyProjects.writeProgram();emergencyProjects.setHour(22);emergencyProjects.writeProgram();System.out.println();System.out.println("**********************************************");}
}
相关文章:
设计模式-第13章(状态模式)
状态模式状态模式状态模式的好处和用处工作状态状态模式 状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况…...
ReentrantLock源码分析(一)加锁流程分析
一、ReetrantLock的使用示例 static ReentrantLock lock new ReentrantLock(); public static void main(String[] args) throws InterruptedException { new Thread(ClassLayOutTest::reentrantLockDemo, "threadA").start(); Thread.sleep(1000);…...
【C++】list的模拟实现
文章目录1.list 底层2. list的模拟实现1. list_node 类设计2. list类如何调用类型3 .push_back(正常实现)4. 迭代器的实现第一个模板参数Tconst迭代器第二个模板参数Ref第三个模板参数Ptr对list封装的理解5. insert6.push_back与 push_front(复用)7. erase8. pop_back与pop_fro…...
Python连接es笔记三之es更新操作
这一篇笔记介绍如何使用 Python 对数据进行更新操作。 对于 es 的更新的操作,不用到 Search() 方法,而是直接使用 es 的连接加上相应的函数来操作,本篇笔记目录如下: 获取连接update()update_by_query()批量更新UpdateByQuery()…...
哪个牌子的蓝牙耳机音质好?音质比较好的蓝牙耳机排名
蓝牙耳机经过多年发展,无论是在外观设计还是性能配置上都有很大的进步,越来越多的蓝牙耳机开始注重音质表现,逐渐有HIFI音质、无损音质出现在大众视野。那么哪个牌子的蓝牙耳机音质好?接下来,我来给大家分享几款音质比…...
Qt实用技巧:Qt中浮点数的相等比较方式(包括单精度和双精度)
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/129464152 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…...
【数据结构初阶】双向循环链表
目录一.链表的分类二.与单链表相比三.实现增删查改1.双向循环链表结构的创建2.创建新节点3.初始化链表4.头插和尾插5.判断链表是否为空6.头删和尾删7.打印函数8.查找函数9.删除pos位置节点10.在pos前位置插入数据11.优化升级一.链表的分类 链表可有根据单向双向、有无哨兵位、…...
0104BeanDefinition合并和BeanClass加载-Bean生命周期详解-spring
文章目录1 前言2 BeanDefinition合并2.1 BeanDefinition合并在做什么?2.2 BeanDefinition怎么合并2.3 示例演示3 Bean Class 加载后记1 前言 下面要介绍的阶段,都是在调用getBean()从容器中获取bean对象的过程中发生的操作,我们需要更多的去…...
Java集合进阶(三)
文章目录一、Map1. 概述2. 基本功能3. 遍历4. 遍历学生对象5. 集合嵌套6. 统计字符出现次数二、Collections1. 常用方法2. 学生对象排序三、模拟斗地主一、Map 1. 概述 Interface Map<K, V>:K 是键的类型,V 是值的类型。 将键映射到值的对象&…...
【网络】什么是RPC?RPC与HTTP有什么关系?
文章目录RPC是什么RPC和HTTP的关系和区别[附]关于REST论文中提到的"HTTP不是RPC"重点参考 凤凰架构-远程过程调用 既然有HTTP为什么还要有RPC? RPC是什么 RPC(Remote Procedure Call):即远程过程调用,目的是为了让计算机能够跟调用…...
[手撕数据结构]栈的深入学习-java实现
CSDN的各位uu们你们好,今天千泽带来了栈的深入学习,我们会简单的用代码实现一下栈, 接下来让我们一起进入栈的神奇小世界吧!0.速览文章一、栈的定义1. 栈的概念2. 栈的图解二、栈的模拟实现三.栈的经典使用场景-逆波兰表达式总结一、栈的定义 1. 栈的概念 栈:一种…...
2.线性表的顺序表示
数据结构很重要! 数据结构很重要!!! 数据结构很重要!!!! 思考 1.线性表的顺序表示内容有哪些?(What) 2.为什么要学线性表的顺序表示? ? (Why)…...
eps文件删除了能恢复吗?恢复误删eps文件的三种方法
eps文件格式专为矢量图像和图形而设计。虽然没有被广泛使用,但它仍然受到各种插画家和平面设计师的钟爱。eps文件十分适合创建徽标和商标设计,主要应用见于广告牌、海报和横幅。可是在使用设备过程中,难免会遇到数据丢失问题,如果…...
【C++】运算符重载练习——Date 类
文章目录👉日期类介绍👈👉日期类实现👈📕 成员变量📕 构造函数📕 对应月份天数📕 赋值重载📕 比较运算符重载📕 计算 运算符重载👉源代码…...
Redis学习(13)之Lua脚本【环境准备】
文章目录一 Lua入门环境准备1.1 Lua简介1.2 Linux 系统安装Lua1.2.1 Lua 下载1.2.2 Lua 安装1.3 Hello World1.3.1 命令行模式1.3.2 脚本文件模式1.3.3 两种脚本运行方式1.4 Win安装Lua1.4.1 LuaForWindows的安装1.4.2 SciTE修改字体大小1.4.3 SciTE中文乱码1.4.4 SciTE快捷键工…...
关于BLE的一些知识总结
数据包长度对于BLE4.0/4.1来说,一个数据包的有效载荷最大为20字节对于BLE4.2以上,数据包的有效载荷扩大为251字节传输速率在不考虑跳频间隔的情况下,最大传输速率为:1)BLE4.0/4.1的理论吞吐率为39kb/s;2&am…...
Spring框架源码分析一
如何看源码(方法论)不要忽略源码中的注释使用翻译工具先梳理脉络,然后梳理细节即总分总,先总体过一遍,再看细节,再做一个总结大胆猜测(8分靠猜),小心验证,再调…...
CSS常用内容总结(扫盲)
文章目录前言相关概念【了解】脚本语言什么是脚本语言脚本语言有什么特点常见的脚本语言什么是动态语言,什么是静态语言动态语言和静态语言两者之间有何区别CSSCSS是什么CSS的特点一、CSS代码怎么写基本语法规则引入方式内部样式内联样式表外部样式代码风格二、CSS的…...
Java启蒙之语言基础
目录 一.Java标识符和关键字 1.1Java标识符 1.2Java关键字 二.数据类型和变量的概述和关系 2.1Java变量 2.2Java的数据类型 2.2.1数据类型的分类的概述 2.2.2数据类型的转换 3.Java运算符 总结 😽个人主页:tq02的博客_CSDN博客-领域博主 &#…...
数据库系统--T-SQL数据查询功能-多表查询(超详细/设计/实验/作业/练习)
目录课程名:数据库系统内容/作用:设计/实验/作业/练习学习:T-SQL数据查询功能-多表查询一、前言二、环境与设备三、内容四、内容练习题目:对应题目答案:五、总结课程名:数据库系统 内容/作用:设…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
