《HeadFirst设计模式(第二版)》第十章代码——状态模式
如下图所示,这是一个糖果机的状态机图,要求使用代码实现:
初始版本:
package Chapter10_StatePattern.Origin;/*** @Author 竹心* @Date 2023/8/19**/public class GumballMachine {final static int SOLD_OUT = 0;final static int NO_QUARTER = 1;final static int HAS_QUARTER = 2;final static int SOLD = 3;int state = SOLD_OUT;int count = 0;public GumballMachine(int count) {this.count = count;if (count > 0) {state = NO_QUARTER;}}public void insertQuarter() {if (state == HAS_QUARTER) {System.out.println("You can't insert another quarter");} else if (state == NO_QUARTER) {state = HAS_QUARTER;System.out.println("You inserted a quarter");} else if (state == SOLD_OUT) {System.out.println("You can't insert a quarter, the machine is sold out");} else if (state == SOLD) {System.out.println("Please wait, we're already giving you a gumball");}}public void ejectQuarter() {if (state == HAS_QUARTER) {System.out.println("Quarter returned");state = NO_QUARTER;} else if (state == NO_QUARTER) {System.out.println("You haven't inserted a quarter");} else if (state == SOLD) {System.out.println("Sorry, you already turned the crank");} else if (state == SOLD_OUT) {System.out.println("You can't eject, you haven't inserted a quarter yet");}}public void turnCrank() {if (state == SOLD) {System.out.println("Turning twice doesn't get you another gumball!");} else if (state == NO_QUARTER) {System.out.println("You turned but there's no quarter");} else if (state == SOLD_OUT) {System.out.println("You turned, but there are no gumballs");} else if (state == HAS_QUARTER) {System.out.println("You turned...");state = SOLD;dispense();}}private void dispense() {if (state == SOLD) {System.out.println("A gumball comes rolling out the slot");count = count - 1;if (count == 0) {System.out.println("Oops, out of gumballs!");state = SOLD_OUT;} else {state = NO_QUARTER;}} else if (state == NO_QUARTER) {System.out.println("You need to pay first");} else if (state == SOLD_OUT) {System.out.println("No gumball dispensed");} else if (state == HAS_QUARTER) {System.out.println("No gumball dispensed");}}public void refill(int numGumBalls) {this.count = numGumBalls;state = NO_QUARTER;}public String toString() {StringBuffer result = new StringBuffer();result.append("\nMighty Gumball, Inc.");result.append("\nJava-enabled Standing Gumball Model #2004\n");result.append("Inventory: " + count + " gumball");if (count != 1) {result.append("s");}result.append("\nMachine is ");if (state == SOLD_OUT) {result.append("sold out");} else if (state == NO_QUARTER) {result.append("waiting for quarter");} else if (state == HAS_QUARTER) {result.append("waiting for turn of crank");} else if (state == SOLD) {result.append("delivering a gumball");}result.append("\n");return result.toString();}
}
上面的代码很明显极其不利于本维护:比如要添加一个新的状态--每次投入25分钱都能有十分之一的概率获得两个糖果。
很明显上面的代码又要添加一堆if-else了,这种情况下就可以使用状态模式:
状态模式:
允许对象内部状态改变时改变其行为。对象看起来好像改变了他的类。
使用了状态模式之后的类图:
State
package Chapter10_StatePattern.State;/*** @Author 竹心* @Date 2023/8/19**/public interface State {public void insertQuarter();//投入25分public void ejectQuarter();//吐出25分钱public void turnCrank();//摇动摇杆public void dispense();//发放public void refill();//填充糖果
}
接下来是五个状态类
NoQuarterState
package Chapter10_StatePattern.State;/*** @Author 竹心* @Date 2023/8/19**///没有25美分
public class NoQuarterState implements State{GumballMachine gumballMachine;public NoQuarterState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertQuarter() {System.out.println("You inserted a quarter");gumballMachine.setState(gumballMachine.getHasQuarterState());}public void ejectQuarter() {System.out.println("You haven't inserted a quarter");}public void turnCrank() {System.out.println("You turned, but there's no quarter");}public void dispense() {System.out.println("You need to pay first");}public void refill() { }public String toString() {return "waiting for quarter";}
}
HasQuarterState
package Chapter10_StatePattern.State;import java.util.Random;/*** @Author 竹心* @Date 2023/8/19**///有25美分
public class HasQuarterState implements State{Random randomWinner = new Random(System.currentTimeMillis());GumballMachine gumballMachine;public HasQuarterState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertQuarter() {System.out.println("You can't insert another quarter");}public void ejectQuarter() {System.out.println("Quarter returned");gumballMachine.setState(gumballMachine.getNoQuarterState());}public void turnCrank() {System.out.println("You turned...");int winner = randomWinner.nextInt(10);if ((winner == 0) && (gumballMachine.getCount() > 1)) {gumballMachine.setState(gumballMachine.getWinnerState());} else {gumballMachine.setState(gumballMachine.getSoldState());}}public void dispense() {System.out.println("No gumball dispensed");}public void refill() { }public String toString() {return "waiting for turn of crank";}
}
SoldState
package Chapter10_StatePattern.State;/*** @Author 竹心* @Date 2023/8/19**/
//糖果已售出
public class SoldState implements State{GumballMachine gumballMachine;public SoldState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertQuarter() {System.out.println("Please wait, we're already giving you a gumball");}public void ejectQuarter() {System.out.println("Sorry, you already turned the crank");}public void turnCrank() {System.out.println("Turning twice doesn't get you another gumball!");}public void dispense() {gumballMachine.releaseBall();if (gumballMachine.getCount() > 0) {gumballMachine.setState(gumballMachine.getNoQuarterState());} else {System.out.println("Oops, out of gumballs!");gumballMachine.setState(gumballMachine.getSoldOutState());}}public void refill() { }public String toString() {return "dispensing a gumball";}
}
SoldOutState
package Chapter10_StatePattern.State;/*** @Author 竹心* @Date 2023/8/19**///糖果已售罄
public class SoldOutState implements State{GumballMachine gumballMachine;public SoldOutState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertQuarter() {System.out.println("You can't insert a quarter, the machine is sold out");}public void ejectQuarter() {System.out.println("You can't eject, you haven't inserted a quarter yet");}public void turnCrank() {System.out.println("You turned, but there are no gumballs");}public void dispense() {System.out.println("No gumball dispensed");}public void refill() {gumballMachine.setState(gumballMachine.getNoQuarterState());}public String toString() {return "sold out";}
}
WinnerState
package Chapter10_StatePattern.State;/*** @Author 竹心* @Date 2023/8/19**///获得两个糖果
public class WinnerState implements State{GumballMachine gumballMachine;public WinnerState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertQuarter() {System.out.println("Please wait, we're already giving you a Gumball");}public void ejectQuarter() {System.out.println("Please wait, we're already giving you a Gumball");}public void turnCrank() {System.out.println("Turning again doesn't get you another gumball!");}public void dispense() {gumballMachine.releaseBall();if (gumballMachine.getCount() == 0) {gumballMachine.setState(gumballMachine.getSoldOutState());} else {gumballMachine.releaseBall();System.out.println("YOU'RE A WINNER! You got two gumballs for your quarter");if (gumballMachine.getCount() > 0) {gumballMachine.setState(gumballMachine.getNoQuarterState());} else {System.out.println("Oops, out of gumballs!");gumballMachine.setState(gumballMachine.getSoldOutState());}}}public void refill() { }public String toString() {return "dispensing two gumballs for your quarter, because YOU'RE A WINNER!";}}
GumballMachine:
package Chapter10_StatePattern.State;/*** @Author 竹心* @Date 2023/8/19**/public class GumballMachine {State soldOutState;State noQuarterState;State hasQuarterState;State soldState;State winnerState;State state = soldOutState;int count = 0;public GumballMachine(int numberGumballs) {soldOutState = new SoldOutState(this);noQuarterState = new NoQuarterState(this);hasQuarterState = new HasQuarterState(this);soldState = new SoldState(this);winnerState = new WinnerState(this);this.count = numberGumballs;if (numberGumballs > 0) {state = noQuarterState;}}public void insertQuarter() {state.insertQuarter();}public void ejectQuarter() {state.ejectQuarter();}public void turnCrank() {state.turnCrank();state.dispense();}void setState(State state) {this.state = state;}void releaseBall() {System.out.println("A gumball comes rolling out the slot...");if (count > 0) {count = count - 1;}}int getCount() {return count;}void refill(int count) {this.count += count;System.out.println("The gumball machine was just refilled; its new count is: " + this.count);state.refill();}public State getState() {return state;}public State getSoldOutState() {return soldOutState;}public State getNoQuarterState() {return noQuarterState;}public State getHasQuarterState() {return hasQuarterState;}public State getSoldState() {return soldState;}public State getWinnerState() {return winnerState;}public String toString() {StringBuffer result = new StringBuffer();result.append("\nMighty Gumball, Inc.");result.append("\nJava-enabled Standing Gumball Model #2004");result.append("\nInventory: " + count + " gumball");if (count != 1) {result.append("s");}result.append("\n");result.append("Machine is " + state + "\n");return result.toString();}
}
GumballMachineTestDrive
package Chapter10_StatePattern.State;import Chapter10_StatePattern.Origin.GumballMachine;/*** @Author 竹心* @Date 2023/8/19**/public class GumballMachineTestDrive {public static void main(String[] args) {GumballMachine gumballMachine =new GumballMachine(10);System.out.println(gumballMachine);gumballMachine.insertQuarter();gumballMachine.turnCrank();gumballMachine.insertQuarter();gumballMachine.turnCrank();System.out.println(gumballMachine);gumballMachine.insertQuarter();gumballMachine.turnCrank();gumballMachine.insertQuarter();gumballMachine.turnCrank();System.out.println(gumballMachine);gumballMachine.insertQuarter();gumballMachine.turnCrank();gumballMachine.insertQuarter();gumballMachine.turnCrank();System.out.println(gumballMachine);gumballMachine.insertQuarter();gumballMachine.turnCrank();gumballMachine.insertQuarter();gumballMachine.turnCrank();System.out.println(gumballMachine);gumballMachine.insertQuarter();gumballMachine.turnCrank();gumballMachine.insertQuarter();gumballMachine.turnCrank();System.out.println(gumballMachine);}
}
相关文章:

《HeadFirst设计模式(第二版)》第十章代码——状态模式
如下图所示,这是一个糖果机的状态机图,要求使用代码实现: 初始版本: package Chapter10_StatePattern.Origin;/*** Author 竹心* Date 2023/8/19**/public class GumballMachine {final static int SOLD_OUT 0;final static int…...

day-25 代码随想录算法训练营(19)回溯part02
216.组合总和||| 思路:和上题一样,差别在于多了总和,但是数字局限在1-9 17.电话号码的字母组合 思路:先纵向遍历第i位电话号码对于的字符串,再横向递归遍历下一位电话号码 93.复原IP地址 画图分析: 思…...
PG逻辑备份与恢复
文章目录 创建测试数据pg_dump 备份pg_restore 恢复pg_restore 恢复并行备份的文件PG 只导出指定函数 创建测试数据 drop database if exists test; create database test ; \c test create table t1(id int primary key); create table t2(id serial primary key, name varch…...

图数据库_Neo4j和SpringBoot整合使用_实战创建明星关系图谱---Neo4j图数据库工作笔记0010
然后我们再来看一下这个明星关系图谱 可以看到这里 这个是原来的startRelation 我们可以写CQL去查询对应的关系 可以看到,首先查询出来以后,然后就可以去创建 我们可以把写的创建明星关系的CQL,拿到 springboot中去执行 可以看到,这里我们先写一个StarRelationRepository,然…...

Linux网络编程:Socket套接字编程(Server服务器 Client客户端)
文章目录: 一:定义和流程分析 1.定义 2.流程分析 3.网络字节序 二:相关函数 IP地址转换函数inet_pton inet_ntop(本地字节序 网络字节序) socket函数(创建一个套接字) bind函数(给socket绑定一个服务器地址结…...

Mac OS下应用Python+Selenium实现web自动化测试
在Mac环境下应用PythonSelenium实现web自动化测试 在这个过程中要注意两点: 1.在终端联网执行命令“sudo pip install –U selenium”如果失败了的话,可以尝试用命令“sudo easy_install selenium”来安装selenium; 2.安装好PyCharm后新建project&…...

每天一道leetcode:934. 最短的桥(图论中等广度优先遍历)
今日份题目: 给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。 岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。 你可以将任意数量的 0 变为 1 &#…...

【学习日记】【FreeRTOS】FreeRTOS 移植到 STM32F103C8
前言 本文基于野火 FreeRTOS 教程,内容是关于 FreeRTOS 官方代码的移植的注意事项,并将野火例程中 STM32F103RC 代码移植到 STM32F103C8。 一、FreeRTOS V9.0.0 源码的获取 两个下载链接: 官 网 代码托管 二、源码文件夹内容简介 Source…...

Qt 屏幕偶发性失灵
项目场景: 基于NXP i.mx7的Qt应用层项目开发,通过goodix使用触摸屏,走i2c协议。 问题描述 触摸屏使用过程中意外卡死,现场分为多种: i2c总线传输错误,直观表现为触摸屏无效,任何与触摸屏挂接在同一总线上的i2c设备,均受到干扰,并且在传输过程中内核报错以下代码: G…...

如何在pycharm中指定GPU
如何在pycharm中指定GPU 作者:安静到无声 个人主页 目录 如何在pycharm中指定GPU打开编辑配置点击环境变量添加GPU配置信息推荐专栏在Pycharm运行程序的时候,有时候需要指定GPU,我们可以采用以下方式进行设置: 打开编辑配置 点击环境变量 添加GPU配置信息 添加名称:CU…...
C#判断字符串中有没有字母,正则表达式、IsLetter
要判断字符串中是否包含字母,可以使用正则表达式或者循环遍历字符串的方式。 方法一:使用正则表达式 using System.Text.RegularExpressions;string input "Hello123"; bool containsLetter Regex.IsMatch(input, "[a-zA-Z]");上…...
Jtti:Ubuntu怎么限制指定端口和IP访问
在 Ubuntu 系统中,可以使用防火墙规则来限制特定的端口和IP访问。常用的防火墙管理工具是 iptables,以下是使用 iptables 来限制指定端口和IP访问的步骤: 安装 iptables: 如果系统中没有安装 iptables,可以使用以下命…...
机器学习/深度学习需要掌握的linux基础命令
很多深度学习/机器学习/数据分析等领域(或者说大多数在Python环境下进行操作的领域)的初学者入门时是在Windows上进行学习,也得益于如Anaconda等工具把环境管理做的如此友善 但如果想在该领域继续深耕,一定会与Linux操作系统打交…...
C++11 std::async推荐使用 std::launch::async 模式
async真假多线程 std::launch::async真多线程 std::launch::async | std::launch::deferred可能多线程 std::launch::deferred假多线程 枚举变量说明 枚举定义 enum class launch {async 1, // 0b1deferred 2, // 0b10any async | def…...
没有使用springboot 单独使用spring-boot-starter-logging
如果您不使用Spring Boot框架,但想单独使用Spring Boot Starter Logging,您可以按照以下步骤进行: 1. 添加Maven依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boo…...

创建Azure资源锁
锁的介绍 在Azure中,资源锁是一种用于保护订阅、资源组或者单个资源的机制。它可以防止对受锁定的资源进行删除或修改操作,帮助确保资源的连续可用性和安全性。 Azure中的资源锁可以分为两种类型: 删除锁(CanNotDelete…...
卷积神经网络教程 (CNN) – 使用 TensorFlow 在 Python 中开发图像分类器
在这篇博客中,让我们讨论什么是卷积神经网络 (CNN) 以及 卷积神经网络背后的架构——旨在解决 图像识别系统和分类问题。 卷积神经网络在图像和视频识别、推荐系统和自然语言处理方面有着广泛的应用。 目录 计算机如何读取图像? 为什么不是全连接网络?...
MyBatis XML映射处理CLOB和BLOB类型
Mybatis的MapperXML映射文件应该处理数据库字段类型为CLOB和BLOB类型的数据呢?首先我们先看下CLOB和BLOB这两种数据类型的介绍。 介绍 使用Mybatis时涉及到两种特殊类型的处理,分别是Blob(Binary Large Object)和Clob࿰…...

FPGA_学习_14_第一个自写模块的感悟和ila在线调试教程与技巧(寻找APD的击穿偏压)
前一篇博客我们提到了,如果要使用算法找到Vbr,通过寻找APD采集信号的噪声方差的剧变点去寻找Vbr是一个不错的方式。此功能的第一步是在FPGA中实现方差的计算,这个我们已经在上一篇博客中实现了。 继上一篇博客之后,感觉过了很久了…...

【2023新教程】树莓派定时自动拍照并上传腾讯云对象存储COS
1 换源 仅适用于Release date: May 3rd 2023、Debian version: 11 (bullseye)这个树莓派OS版本,其他版本不保证有效。 首先使用如下命令,查看自己树莓派的架构。 uname -a结果如下: 如果红圈处显示为aarch64,使用命令sudo na…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...