当前位置: 首页 > news >正文

Java编程之状态模式

引言

“人生如戏,全靠状态。”——设计模式也深知这一点。


一、什么是状态模式(State Pattern)

状态模式是一种行为型设计模式,允许对象在内部状态改变时,改变它的行为。也就是说,看起来像是修改了它的类

通俗解释

就像一只电风扇,有关机状态低速状态高速状态。你按下按钮,它就在不同的状态间切换。状态决定了电风扇的行为


二、示例讲解:

本篇我们以“自动售货机 Vending Machine”为例。它可能处于以下状态:

  • 等待投币
  • 已投币,等待选择
  • 正在出货
  • 售罄

用户的操作行为(如投币、选择商品、取货)会根据当前状态产生不同的响应。


三、UML 图结构(PlantUML):

@startuml
interface State {+insertCoin()+selectProduct()+dispense()
}class WaitingForCoin implements State
class HasCoin implements State
class Dispensing implements State
class SoldOut implements Stateclass VendingMachine {-state: State+setState(s: State)+insertCoin()+selectProduct()+dispense()
}State <|.. WaitingForCoin
State <|.. HasCoin
State <|.. Dispensing
State <|.. SoldOut
VendingMachine --> State
@enduml

在这里插入图片描述


四、Java 实现代码

状态接口

public interface State {void insertCoin();void selectProduct();void dispense();
}

具体状态实现

等待投币状态

public class WaitingForCoinState implements State {private VendingMachine machine;public WaitingForCoinState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("硬币已投入。");machine.setState(machine.getHasCoinState());}@Overridepublic void selectProduct() {System.out.println("请先投币!");}@Overridepublic void dispense() {System.out.println("不能发货,请先投币并选择商品。");}
}

已投币状态

public class HasCoinState implements State {private VendingMachine machine;public HasCoinState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("已经有硬币了,请先选择商品。");}@Overridepublic void selectProduct() {System.out.println("商品已选择,正在出货...");machine.setState(machine.getDispensingState());}@Overridepublic void dispense() {System.out.println("请先选择商品!");}
}

出货中状态

public class DispensingState implements State {private VendingMachine machine;public DispensingState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("正在出货,请稍候...");}@Overridepublic void selectProduct() {System.out.println("已经选择了,请等待出货。");}@Overridepublic void dispense() {System.out.println("出货完成!");if (machine.getProductCount() > 0) {machine.setState(machine.getWaitingForCoinState());} else {System.out.println("商品售罄!");machine.setState(machine.getSoldOutState());}}
}

售罄状态

public class SoldOutState implements State {private VendingMachine machine;public SoldOutState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("商品已售罄,请勿投币。");}@Overridepublic void selectProduct() {System.out.println("无法选择商品,已售罄。");}@Overridepublic void dispense() {System.out.println("无法出货,商品售罄。");}
}

状态持有者:VendingMachine 类

public class VendingMachine {private State waitingForCoinState;private State hasCoinState;private State dispensingState;private State soldOutState;private State currentState;private int productCount;public VendingMachine(int initialCount) {waitingForCoinState = new WaitingForCoinState(this);hasCoinState = new HasCoinState(this);dispensingState = new DispensingState(this);soldOutState = new SoldOutState(this);this.productCount = initialCount;this.currentState = initialCount > 0 ? waitingForCoinState : soldOutState;}public void insertCoin() {currentState.insertCoin();}public void selectProduct() {currentState.selectProduct();}public void dispense() {currentState.dispense();if (productCount > 0 && currentState == dispensingState) {productCount--;}}// Getters & Setterspublic void setState(State state) {this.currentState = state;}public State getWaitingForCoinState() { return waitingForCoinState; }public State getHasCoinState() { return hasCoinState; }public State getDispensingState() { return dispensingState; }public State getSoldOutState() { return soldOutState; }public int getProductCount() { return productCount; }
}

测试代码

public class Main {public static void main(String[] args) {VendingMachine machine = new VendingMachine(2);machine.insertCoin();machine.selectProduct();machine.dispense();machine.insertCoin();machine.selectProduct();machine.dispense();// 尝试再买一次machine.insertCoin();machine.selectProduct();machine.dispense();}
}

五、总结:状态模式的优缺点

优点:

  • 封装状态转换逻辑,消除了大量 if-else
  • 新状态扩展易如反掌
  • 状态切换透明,对外接口不变

缺点:

  • 类数量变多(每个状态一个类)
  • 状态之间可能耦合紧密

六、适用场景

  • 对象行为依赖于状态变化(如:文档编辑器、交通灯、媒体播放器)
  • 状态可枚举、行为可切换,但不适合用大量 if/else 处理

七、参考

《23种设计模式概览》

在这里插入图片描述

http://www.dtcms.com/a/263620.html

相关文章:

  • 《UE5_C++多人TPS完整教程》学习笔记40 ——《P41 装备(武器)姿势(Equipped Pose)》
  • 基于Socketserver+ThreadPoolExecutor+Thread构造的TCP网络实时通信程序
  • mac重复文件清理,摄影师同款清理方案
  • flv.js视频/直播流测试demo
  • 2025 推理技术风向标:DeepSeek-R1 揭示大模型从 “记忆” 到 “思考” 的进化路径
  • 【linux】基础开发工具(1)
  • Flink Savepoints 总结
  • js代码09
  • Spring Boot WebSocket方案终极指南:Netty与官方Starter对比与实践
  • MFC的List Control自适应主界面大小
  • Android Gradle 插件和 Android Studio 兼容性
  • Windows下配置Docker+WSL集成开发环境
  • 【C#】如果有一个数值如 168.0000100,如何去除末尾的无效零,只显示有效的小数位数,让DeepSeek给我们解答
  • 飞算JavaAI—AI编程助手 | 编程领域的‘高科技指南针’,精准导航开发!
  • 小米YU7使用UWB技术,厘米级定位精准迎宾,安全防破解无感控车
  • CentOS系统新手指导手册
  • 微信小程序实现table表格
  • 【锂电池剩余寿命预测】GRU门控循环单元锂电池剩余寿命预测(Pytorch完整源码和数据)
  • 清理 Docker 缓存占用
  • 前端常用构建工具介绍及对比
  • 西交从语义到关系、重塑具身导航策略!RSRNav:基于空间关系推理的图像目标导航
  • android stdio 创建 mediaplayertest
  • SpringBoot+MySQL旅游资源管理系统Java源码
  • Reactor ConnectableFlux支持多订阅者
  • OpenCV CUDA模块设备层-----双曲正切函数tanh()
  • IDEA相关配置记录
  • 基于Python的GIS-RS多源数据处理(TIF/SHP/NC/...)【20250630】
  • 国产化替换中政务行业通用的解决方案是什么?需要注意的事项有哪些?
  • 03认证原理自定义认证添加认证验证码
  • Android阴影效果的艺术与实现:从入门到精通