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

devtools/2024/11/14 21:51:06/

状态模式

文章目录

什么是状态模式

状态模式(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);}@Overridepublic void insertCoin(int amount) {System.out.println("接受硬币 " + amount + " 元");vendingMachine.setState(new HasCoinState(vendingMachine)); // 改变状态为已投币状态}// 其他方法的实现,由于当前状态无硬币,通常拒绝执行相关操作@Overridepublic void ejectCoin() {System.out.println("未投币,无法取消");}@Overridepublic void selectProduct(String product) {System.out.println("请先投入硬币");}@Overridepublic void dispenseProduct() {System.out.println("请先投入硬币并选择商品");}@Overridepublic void giveChange() {System.out.println("请先完成购买");}
}
public class HasCoinState extends VendingMachineState {public HasCoinState(VendingMachine vendingMachine) {super(vendingMachine);}@Overridepublic 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.ppmy.cn/devtools/6594.html

相关文章

CSS3 max/min-content及fit-content、fill-available值的详解

c3中对width的值多了几个值&#xff1a;fill-available, max-content, min-content, 以及fit-content。 1.width:fill-available 我们在页面中扔一个没有其他样式的<div>元素&#xff0c;则&#xff0c;此时&#xff0c;该<div>元素的width表现就是fill-availabl…

c++11 标准模板(STL)本地化库 - 平面类别(std::collate) - 定义字典序比较和字符串的散列(三)

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 定义字典序比较和字符串的散列 std::collate template< class…

东岸科技将赴港IPO,冲刺催收第一股

来源 | 镭射财经&#xff08;leishecaijing&#xff09; 「镭射财经」独家获悉&#xff0c;东岸科技即将开启IPO&#xff0c;向港交所递交上市申请。计划上市的为公司科技板块&#xff0c;拟募集资金主要用于不良资产管理数字化创新。 今年3月&#xff0c;东岸科技董事长朱铁…

数据结构习题--杨辉三角形(返回某一行)

数据结构习题–杨辉三角形(返回某一行) 输入需要第几行&#xff0c;返回杨辉三角形中的这一行 注意&#xff1a;这里的行数是从0开始 方法&#xff1a;递推(复杂度行数的平方) 分析&#xff1a; 当处于每行的第一个和最后一个时&#xff0c;添加的数为1 除此之外&#xff0…

MacOS 文件句柄数不够 Error: EMFILE: too many open files

MacOS 文件句柄数不够 Error: EMFILE: too many open files 直奔主题-解决方案 启动项目发现报错&#xff1a;Error: EMFILE: too many open files&#xff1b;经排查是因为单个微应用项目较大&#xff0c;发布过程中已经超过了mac默认的文件监听上限对文件系统进行大量并发调用…

Tomcat命令行窗口、IDEA中Tomcat控制台 中文乱码问题解决方案

Tomcat出现中文乱码问题 打开Tomcat文件夹下的conf/logging.properties文件&#xff0c;将下图位置中的编码由UTF-8全部替换成GBK 然后重启Tomcat服务器&#xff0c;问题解决 Intellij IDEA启动Tomcat服务器控制台出现中文乱码 解决方案非常简单&#xff0c;按照下图设置控制…

代码随想录系统性一刷总结

代码随想录系统性一刷总结 数组 指针思想很重要 day01 二分查找移除元素 day02 数组平方长度最小子数组螺旋矩阵II 链表 链表结点的增删改查&#xff0c;头结点的运用&#xff0c;灵活运用指针 day03 移除链表元素设计链表翻转链表 day04 交换结点删除结点链表相交环形列表 …

uni-app学习记录

uni-app 基础 uni-app环境搭建 命令行搭建 基础使用差异说明 要使用滚动 <scroll-view scroll-y"true" class"h-600">类似于v-html <rich-text nodes"<h1>1123213</h1>" /> <editor /> - text-area生命周期…