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

状态模式(State Pattern)

🧠 状态模式(State Pattern)

状态模式是一种行为型设计模式。它允许对象在其内部状态改变时改变其行为。一个对象的行为会随着它的状态改变而改变,状态模式可以帮助你处理对象在不同状态下的行为分支问题,使得对象的行为看起来像是“改变了类”。


🎯 为什么需要状态模式?

  1. 处理复杂的状态转移:当对象的行为受不同状态控制,并且状态之间的转移规则复杂时,使用状态模式可以清晰地处理不同的状态及其转移。
  2. 避免条件语句:通过将状态转移的逻辑分散到各个状态类中,避免了在主类中大量的条件语句(如 if-elseswitch)。
  3. 扩展性:每个状态都封装成独立的类,新的状态可以轻松地添加到系统中,避免修改原有代码。

优缺点分析

优点缺点
状态转换清晰,易于管理增加了类的数量,系统变得更复杂
使得行为随状态变化,代码更加灵活对于简单场景,状态模式可能显得过于复杂
易于扩展,增加新状态时只需新增类状态类之间的关系可能难以理清

🧩 Python 示例:售卖机状态管理

我们通过一个售卖机的例子来展示状态模式。假设售卖机有三个状态:NoCoin(无硬币)、HasCoin(有硬币)、SoldOut(已售空),每个状态下,售卖机的行为不同。


1️⃣ 状态接口(State)

首先定义一个状态接口,所有具体状态类都要实现这个接口中的方法。这里用 Python 的 ABC 类来定义抽象类。

from abc import ABC, abstractmethodclass State(ABC):@abstractmethoddef insert_coin(self):pass@abstractmethoddef eject_coin(self):pass@abstractmethoddef turn_crank(self):pass@abstractmethoddef dispense(self):pass
  • State 类是一个抽象基类,包含了四个方法:

    • insert_coin():投币方法。
    • eject_coin():退币方法。
    • turn_crank():转动曲柄的方法。
    • dispense():发放商品的方法。

这些方法会被具体的状态类实现,来定义每个状态下如何响应这些操作。

2️⃣ 具体状态类(Concrete States)

接下来我们定义具体的状态类。每个状态类实现了 State 接口,并定义了不同的行为。

class NoCoinState(State):def __init__(self, machine):self.machine = machinedef insert_coin(self):'''难点:状态转移-self.machine:指的是当前的 VendingMachine 对象(售卖机)。-self.machine.no_coin_state:这是 VendingMachine 类中的一个属性,表示售卖机当前处于 NoCoinState 状态(即没有投入硬币的状态)。no_coin_state 是 VendingMachine 类的一个状态实例,属于 NoCoinState 类型。-self.machine.set_state(self.machine.no_coin_state):这行代码的作用是通过set_state() 方法,将售卖机的当前状态设置为 NoCoinState。即将售卖机的状态转为 "没有硬币"。'''print("Coin inserted")self.machine.set_state(self.machine.has_coin_state)def eject_coin(self):print("No coin to eject")def turn_crank(self):print("Insert coin first!")def dispense(self):print("Insert coin first!")class HasCoinState(State):def __init__(self, machine):self.machine = machinedef insert_coin(self):print("Coin already inserted")def eject_coin(self):print("Coin ejected")self.machine.set_state(self.machine.no_coin_state)def turn_crank(self):print("Turn crank")self.machine.set_state(self.machine.sold_out_state)self.machine.dispense()def dispense(self):print("No item dispensed")class SoldOutState(State):def __init__(self, machine):self.machine = machinedef insert_coin(self):print("Machine is sold out")def eject_coin(self):print("No coin to eject")def turn_crank(self):print("No item to dispense")def dispense(self):print("Machine is sold out")
  • NoCoinState:表示没有硬币的状态。投币后状态转到 HasCoinState
  • HasCoinState:表示已经投币的状态。转动曲柄时,状态转到 SoldOutState 并发放商品。
  • SoldOutState:表示售卖机售罄的状态。无法投币和转动曲柄。

3️⃣ 上下文类(VendingMachine)

然后,我们创建一个 上下文类(在状态模式中,通常是管理状态的核心类),这个类用于管理当前的状态以及切换状态。

class VendingMachine:def __init__(self):self.no_coin_state = NoCoinState(self)self.has_coin_state = HasCoinState(self)self.sold_out_state = SoldOutState(self)self.state = self.no_coin_state  # 初始状态是没有投币def set_state(self, state: State):self.state = statedef insert_coin(self):self.state.insert_coin()def eject_coin(self):self.state.eject_coin()def turn_crank(self):self.state.turn_crank()def dispense(self):self.state.dispense()
  • VendingMachine 类管理了所有的状态,并通过 set_state() 方法来切换当前的状态。
  • 每个方法(如 insert_coin()eject_coin() 等)都会调用当前状态的相应方法,从而实现不同状态下不同的行为。

4️⃣ 客户端代码:模拟使用售卖机

最后,我们编写客户端代码,模拟售卖机的操作过程。客户可以投币、转动曲柄以及退币。

# 创建一个售卖机对象
vending_machine = VendingMachine()# 测试状态切换
vending_machine.insert_coin()  # 投币
vending_machine.turn_crank()   # 转动曲柄,发放商品
vending_machine.eject_coin()  # 退币# 再次测试
vending_machine.insert_coin()  # 投币
vending_machine.turn_crank()   # 转动曲柄,发放商品

输出结果

Coin inserted
Turn crank
No item dispensed
Coin ejected
Coin inserted
Turn crank
No item dispensed
  • insert_coin() 被调用时,状态从 NoCoinState 转变为 HasCoinState
  • turn_crank() 被调用时,状态从 HasCoinState 转变为 SoldOutState,并执行发放商品的操作。

🧭 类图(Mermaid)

状态管理
使用状态
使用状态
使用状态
«interface»
State
+insert_coin()
+eject_coin()
+turn_crank()
+dispense()
NoCoinState
+insert_coin()
+eject_coin()
+turn_crank()
+dispense()
HasCoinState
+insert_coin()
+eject_coin()
+turn_crank()
+dispense()
SoldOutState
+insert_coin()
+eject_coin()
+turn_crank()
+dispense()
VendingMachine
+insert_coin()
+eject_coin()
+turn_crank()
+dispense()

🧭 流程图(Mermaid)

User VendingMachine NoCoinState HasCoinState SoldOutState insert_coin() insert_coin() state change turn_crank() turn_crank() state change dispense() eject_coin() eject_coin() User VendingMachine NoCoinState HasCoinState SoldOutState

🧠 应用场景总结

场景示例
状态机游戏中角色的状态切换,如“待机”,“攻击”,“防御”
流程管理任务处理的多个步骤,进度状态控制
GUI设计按钮或控件的不同状态响应,例如“启用”,“禁用”
电梯系统电梯的“上行”,“下行”,“空闲”等状态

总结口诀

状态模式
允许对象根据内部状态改变其行为,避免大量的条件语句
✅ 每个状态封装成独立类,简化状态转移逻辑,使代码易于维护和扩展。


希望这次的例子更清晰了!如果有其他问题或需要进一步的解释,随时告诉我!

http://www.xdnf.cn/news/4003.html

相关文章:

  • 电子商务商家后台运营专员模板
  • C++ 中二级指针的正确释放方法
  • 【KWDB 创作者计划】_Ubuntu 22.04系统KWDB数据库安装部署使用教程
  • Qt中的UIC
  • Amazon Bedrock Converse API:开启对话式AI新体验
  • Qt开发:容器组控件的介绍和使用
  • 20、数据可视化:魔镜报表——React 19 图表集成
  • 408考研逐题详解:2009年第8题
  • Java后端程序员学习前端之CSS
  • Python matplotlib 成功使用SimHei 中文字体
  • 详解RabbitMQ工作模式之发布订阅模式
  • 基于C++实现的深度学习(cnn/svm)分类器Demo
  • Baklib知识中台:智能服务架构新实践
  • 【算法学习】递归、搜索与回溯算法(一)
  • python函数复习(形参实参,收集参数,关键字参数)
  • uniapp中用canvas绘制简单柱形图,小容量,不用插件——简单使用canvas
  • QT 在圆的边界画出圆
  • IP属地是我的定位吗?——解析两者区别
  • Python异步编程入门:从同步到异步的思维转变
  • VBA信息获取与处理专题五:VBA利用CDO发送电子邮件
  • 【外围电路】按键电路设计外接信号输入设计
  • Go小技巧易错点100例(二十九)
  • rollout 是什么:机器学习(强化学习)领域
  • 【Vue】Vue3源码解析与实现原理
  • 关于 dex2oat 以及 vdex、cdex、dex 格式转换
  • VLA算法总结对比——RT1 / RT2 / Pi0 / Octo/ RDT / OpenVLA
  • 钩子函数和参数:Vue组件生命周期中的自定义逻辑
  • 2.3 向量组
  • Linux电源管理(6)_Generic PM之挂起功能
  • Ubuntu K8S(1.28.2) 节点/etc/kubernetes/manifests 不存在