状态模式(状态和行为分离)

状态模式

文章目录

  • 状态模式
    • 什么是状态模式
    • 状态模式好处与用处
    • 什么时候考虑使用状态模式
    • 通过示例了解状态模式

什么是状态模式

状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断
逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简
单,那就没必要用‘状态模式了

  • Context:维护一个ConcreteState子类的实例,这个实例定义当前的状态
  • State:抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
  • 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为

状态模式好处与用处

状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来

将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换

这样做的目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难以修改和扩展,就像我们最早说的刻版印刷一样,任何改动和变化都是致命的。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖,好比把整个版面改成了一个又一个的活字,此时就容易维护和扩展了

什么时候考虑使用状态模式

当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了

通过示例了解状态模式

状态模式是一种行为设计模式,它允许一个对象在其内部状态改变时改变其行为。这种模式将对象的状态与其行为解耦,使得状态的变化不影响对象接口。下面是一个使用 Java 实现状态模式的示例,以一个自动售货机为例,它具有不同的硬币投入状态,并根据当前状态决定是否接受硬币、是否可以购买商品以及找零等行为。

1.首先,定义一个 VendingMachineState 抽象类(或接口),声明所有可能的状态行为:

public abstract class VendingMachineState {
    protected VendingMachine vendingMachine; // 售货机对象,用于状态切换

    public VendingMachineState(VendingMachine vendingMachine) {
        this.vendingMachine = vendingMachine;
    }

    // 抽象方法,由子类实现具体的业务逻辑
    public abstract void insertCoin(int amount); // 投入硬币
    public abstract void ejectCoin(); // 取消投币
    public abstract void selectProduct(String product); // 选择商品
    public abstract void dispenseProduct(); // 出货
    public abstract void giveChange(); // 找零
}

2.接下来,为自动售货机创建几种具体的状态类,每种状态类继承自 VendingMachineState 并实现其抽象方法:

public class NoCoinState extends VendingMachineState {
    public NoCoinState(VendingMachine vendingMachine) {
        super(vendingMachine);
    }

    @Override
    public void insertCoin(int amount) {
        System.out.println("接受硬币 " + amount + " 元");
        vendingMachine.setState(new HasCoinState(vendingMachine)); // 改变状态为已投币状态
    }

    // 其他方法的实现,由于当前状态无硬币,通常拒绝执行相关操作
    @Override
    public void ejectCoin() {
        System.out.println("未投币,无法取消");
    }

    @Override
    public void selectProduct(String product) {
        System.out.println("请先投入硬币");
    }

    @Override
    public void dispenseProduct() {
        System.out.println("请先投入硬币并选择商品");
    }

    @Override
    public void giveChange() {
        System.out.println("请先完成购买");
    }
}
public class HasCoinState extends VendingMachineState {
    public HasCoinState(VendingMachine vendingMachine) {
        super(vendingMachine);
    }

    @Override
    public void insertCoin(int amount) {
        System.out.println("接受硬币 " + amount + " 元");
    }

    // 其他方法的实现,如允许用户选择商品、出货、找零等
    // ...
}

// 可以根据需要添加更多状态类,如 InsufficientCoinState(金额不足状态)、ProductSelectedState(商品已选状态)

3.最后,定义 VendingMachine 类,包含状态字段及状态切换的相关方法:

public class VendingMachine {
    private VendingMachineState state;

    public VendingMachine() {
        setState(new NoCoinState(this)); // 初始化状态为无硬币状态
    }

    public void setState(VendingMachineState state) {
        this.state = state;
    }

    public void insertCoin(int amount) {
        state.insertCoin(amount);
    }

    public void ejectCoin() {
        state.ejectCoin();
    }

    public void selectProduct(String product) {
        state.selectProduct(product);
    }

    public void dispenseProduct() {
        state.dispenseProduct();
    }

    public void giveChange() {
        state.giveChange();
    }
}

4.现在,您可以创建一个 VendingMachine 对象并模拟用户的操作:

public class Main {
    public static void main(String[] args) {
        VendingMachine vendingMachine = new VendingMachine();

        vendingMachine.insertCoin(5); // 投入5元硬币
        vendingMachine.selectProduct("Coke"); // 选择可乐
        vendingMachine.insertCoin(3); // 再投入3元硬币
        vendingMachine.dispenseProduct(); // 出货
        vendingMachine.giveChange(); // 找零
    }
}

在这个示例中,VendingMachine 类依赖于其内部状态对象(VendingMachineState 的子类)来决定如何响应外部事件。当状态发生变化时,VendingMachine 会切换到相应的新状态对象,从而改变其行为。通过这种方式,状态模式实现了状态与行为的分离,使得状态转换和状态相关行为的增加变得容易且灵活。

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

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

相关文章

【YOLOv8改进[检测头Head]】YOLOv8的“新头”之动态头(DynamicHead)

目录 一 DynamicHead 二 YOLOv8的“新头”之动态头 1 总体修改 2 配置文件 3 训练 其他 一 DynamicHead 官方论文地址:https://arxiv.org/pdf/2106.08322.pdf 官方代码地址:GitCode - 开发者的代码家园 在计算机视觉应用中,目标检测…

启动appium服务的2种方法(python脚本cmd窗口)

1.通过cmd窗口命令来启动 2.通过python代码启动 2.1启动单个appium服务 2.2启动多个appium服务 3.端口说明 一.端口号设置Appium服务器端口:4723 bp端口:4724 Appium服务器端口:4725 bp端口:4726可以看到appium服务器端口和bp端…

SpringBoot(一)【入门】

前言 1、SpringBoot 快速入门 1.1、SpringBoot 简介 SpringBoot 是用来简化 Spring 应用的初始搭建以及开发过程 首先我们回顾一下 SpringMVC 项目的开发过程: 导入依赖(javax.servlet-api 和 spring-webmvc)Servlet 容器配置类&#xff…

VirtualBox虚拟机使用win11系统,忘记密码如何重置密码

1. 点击重启同时按住Shift(按住不放) 2. 直到出现下面的界面,释放Shift,并进入疑难解答 3. 进入高级选项 4. 进入命令提示符 5. 发现当前是在X盘? 6. 进入C:\Windows\System32 c: cd Windows\System32 7. 备份osk.exe…

SpringCloud系列(5)--SpringCloud微服务工程公共部分提取

前言:在上一章节中我们创建了两个个SpringCloud工程,但在两个工程中分别存在着一些重复的部分,例如重复的实体类(如图所示),这样会造成系统的冗余,所以我们需要把公共的类提取到一个工程里&…

预约小程序新选择:强大后端管理功能一览

拥有一个功能齐全、操作便捷的小程序对于商家来说至关重要。为了满足广大商家的需求,乔拓云平台提供了丰富的模板资源,帮助用户快速搭建预约型小程序,并配备了强大的后端管理功能,让商家能够轻松管理预约订单,提升运营…

Centos7 ElasticSearch集群搭建

1. 服务器环境配置 1.1 配置hosts文件 3台服务器都要执行 vim /etc/hosts; # 将以下内容写入3台服务器hosts文件 192.168.226.148 es001 192.168.226.149 es002 192.168.226.150 es003 1.2 关闭防火墙 3台服务器都要执行 systemctl stop firewalld; systemctl disable…

【opencv】dnn示例-speech_recognition.cpp 使用DNN模块结合音频信号处理技术实现的英文语音识别...

模型下载地址: https://drive.google.com/drive/folders/1wLtxyao4ItAg8tt4Sb63zt6qXzhcQoR6 终端输出:(audio6.mp3 、audio10.mp3) [ERROR:00.002] global cap_ffmpeg_impl.hpp:1112 open VIDEOIO/FFMPEG: unsupported parameter…

# 从浅入深 学习 SpringCloud 微服务架构(一)基础知识

从浅入深 学习 SpringCloud 微服务架构(一)基础知识 1、系统架构演变: 1)单体应用架构。如电商项目。 用户管理、商品管理、订单管理,在一个模块里。 优点:开发简单,快速,适用于…

Mac下brew安装php7.4

这里作者挂了梯子,所以很流畅! brew的下载,可参考另外一篇博文~Homebrew 安装与卸载 1、将第三方仓库加入brew brew tap shivammathur/php2、安装指定版本的PHP brew install php7.43、替换Mac自带PHP环境并刷新环境变量 -> …

基于simulink的模拟锁相环和数字锁相环建模与对比仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 模拟锁相环(PLL)的基本原理 4.2 数字锁相环(DPLL)的基本原理 5.完整工程文件 1.课题概述 模拟锁相环和数字锁相环建模的simulink建模,对…

OpenHarmony UI动画-recyclerview_animators

简介 带有添加删除动画效果以及整体动画效果的list组件库 下载安装 ohpm install ohos/recyclerview-animatorsOpenHarmony ohpm 环境配置等更多内容,请参考如何安装OpenHarmony ohpm 包 使用说明 引入组件库 import { RecyclerView } from "ohos/recycler…

Qt/C++音视频开发70-无感切换通道/无缝切换播放视频/多通道流畅切换/不同视频打开无缝切换

一、前言 之前就写过这个方案,当时做的是ffmpeg内核版本,由于ffmpeg内核解析都是代码实现,所以无缝切换非常完美,看不到丝毫的中间切换过程,看起来就像是在一个通道画面中。其实这种切换只能说是取巧办法,…

排序算法之计数排序

目录 一、简介二、代码实现三、应用场景 一、简介 算法平均时间复杂度最好时间复杂度最坏时间复杂度空间复杂度排序方式稳定性计数排序O(nk )O(nk)O(nk)O(k)Out-place稳定 稳定:如果A原本在B前面,而AB,排序之后A仍然在B的前面; 不…

稀碎从零算法笔记Day52-LeetCode:从双倍数组中还原原数组

题型:数组、贪心 链接:2007. 从双倍数组中还原原数组 - 力扣(LeetCode) 来源:LeetCode 题目描述 一个整数数组 original 可以转变成一个 双倍 数组 changed ,转变方式为将 original 中每个元素 值乘以 …

记录ubuntu20.04安装nvidia-525.85.05显卡驱动(学习笔记2024.4.15、4.16)

电脑:华硕天选X2024 显卡:4060Ti i5-14400F 架构:x86_64 我需要使用Linux系统使用IsaacSim进行仿真,所以安装的都是IsaacSim中的推荐版本。 一.对新鲜的电脑进行分盘 电脑刚到手,900多个G全在C盘里,给它…

学习笔记(4月18日)vector底层模拟实现(1)

1.迭代器 vector实际上是由迭代器进行维护的,关于迭代器是什么,为什么要叫这个名字,后面的学习会逐渐了解,现在先将迭代器是作为指针即可。 vector底层有三个迭代器,用来起到容量、数组头、元素个数的作用。 同时为…

数字零售力航母-看微软如何重塑媒体

数字零售力航母-看微软如何重塑媒体 - 从2024全美广播协会展会看微软如何整合营销媒体AI技术和AI平台公司 2024年,微软公司联合英伟达总司,赞助全美广播协会展会。本次展会微软通过搭建一个由全面的合作伙伴生态系统支持的可信和安全的平台,…

RIP最短路实验(华为)

思科设备参考:RIP最短路实验(思科) 一,技术简介 RIP(Routing Information Protocol,路由信息协议)是一种基于距离矢量的内部网关协议,工作原理是每个路由器周期性地向邻居路由器发…

【网站项目】新生报到系统小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…
最新文章