状态模式
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read472 words

状态模式

状态模式(State Pattern)允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

问题定义

场景1:自动售货机

# ❌ 问题:大量条件判断
class VendingMachine:
"""自动售货机"""
def __init__(self):
self.has_coin = False
self.has_item = True
def insert_coin(self):
if not self.has_coin:
print("投入硬币")
self.has_coin = True
else:
print("已有硬币,请选择商品")
def select_item(self):
if self.has_coin:
if self.has_item:
print("取出商品")
self.has_coin = False
else:
print("商品已售罄")
else:
print("请先投币")
def return_coin(self):
if self.has_coin:
print("退还硬币")
self.has_coin = False
else:
print("没有硬币可退")
# 问题:每个方法都要检查所有状态
# 状态越多,条件判断越多,代码越复杂

场景2:订单状态

# ❌ 问题:状态转换逻辑分散
class Order:
"""订单"""
def __init__(self):
self.state = "pending"
def confirm(self):
if self.state == "pending":
print("订单已确认")
self.state = "confirmed"
else:
print("当前状态无法确认")
def ship(self):
if self.state == "confirmed":
print("订单已发货")
self.state = "shipped"
else:
print("当前状态无法发货")
def deliver(self):
if self.state == "shipped":
print("订单已送达")
self.state = "delivered"
else:
print("当前状态无法送达")
def cancel(self):
if self.state in ["pending", "confirmed"]:
print("订单已取消")
self.state = "cancelled"
else:
print("当前状态无法取消")
# 问题:每个操作都要检查状态
# 添加新状态需要修改所有方法

解决方案

状态模式将状态封装成独立的类,行为随状态改变而改变。

classDiagram class State { <> +handle() } class ConcreteStateA { +handle() } class ConcreteStateB { +handle() } class Context { -state: State +setState() +request() } State <|-- ConcreteStateA State <|-- ConcreteStateB Context o-- State : uses

标准实现

状态接口

from abc import ABC, abstractmethod
class VendingMachineState(ABC):
"""售货机状态接口"""
@abstractmethod
def insert_coin(self, machine):
pass
@abstractmethod
def select_item(self, machine):
pass
@abstractmethod
def return_coin(self, machine):
pass

具体状态

class NoCoinState(VendingMachineState):
"""无硬币状态"""
def insert_coin(self, machine):
print("投入硬币")
machine.set_state(HasCoinState())
def select_item(self, machine):
print("请先投币")
def return_coin(self, machine):
print("没有硬币可退")
class HasCoinState(VendingMachineState):
"""有硬币状态"""
def insert_coin(self, machine):
print("已有硬币")
def select_item(self, machine):
print("取出商品")
machine.set_state(NoCoinState())
def return_coin(self, machine):
print("退还硬币")
machine.set_state(NoCoinState())

上下文

class VendingMachine:
"""售货机 - 上下文"""
def __init__(self):
self._state = NoCoinState()
def set_state(self, state):
"""设置状态"""
self._state = state
def insert_coin(self):
"""投币"""
self._state.insert_coin(self)
def select_item(self):
"""选择商品"""
self._state.select_item(self)
def return_coin(self):
"""退币"""
self._state.return_coin(self)

客户端使用

# 创建售货机
machine = VendingMachine()
print("初始状态:")
machine.insert_coin()
machine.select_item()
print("\n再次投币:")
machine.insert_coin()
print("\n退币:")
machine.return_coin()
print("\n选择商品(无币):")
machine.select_item()

实战应用

应用1:订单状态管理

from abc import ABC, abstractmethod
class OrderState(ABC):
"""订单状态接口"""
@abstractmethod
def confirm(self, order):
pass
@abstractmethod
def ship(self, order):
pass
@abstractmethod
def deliver(self, order):
pass
@abstractmethod
def cancel(self, order):
pass
def __str__(self):
return self.__class__.__name__
class PendingState(OrderState):
"""待确认状态"""
def confirm(self, order):
print("订单已确认")
order.set_state(ConfirmedState())
def ship(self, order):
print("订单未确认,无法发货")
def deliver(self, order):
print("订单未发货,无法送达")
def cancel(self, order):
print("订单已取消")
order.set_state(CancelledState())
class ConfirmedState(OrderState):
"""已确认状态"""
def confirm(self, order):
print("订单已确认,无需再次确认")
def ship(self, order):
print("订单已发货")
order.set_state(ShippedState())
def deliver(self, order):
print("订单未发货,无法送达")
def cancel(self, order):
print("订单已取消")
order.set_state(CancelledState())
class ShippedState(OrderState):
"""已发货状态"""
def confirm(self, order):
print("订单已发货,无法确认")
def ship(self, order):
print("订单已发货,无需再次发货")
def deliver(self, order):
print("订单已送达")
order.set_state(DeliveredState())
def cancel(self, order):
print("订单已发货,无法取消")
class DeliveredState(OrderState):
"""已送达状态"""
def confirm(self, order):
print("订单已送达,无法确认")
def ship(self, order):
print("订单已送达,无法发货")
def deliver(self, order):
print("订单已送达,无需再次送达")
def cancel(self, order):
print("订单已送达,无法取消")
class CancelledState(OrderState):
"""已取消状态"""
def confirm(self, order):
print("订单已取消,无法确认")
def ship(self, order):
print("订单已取消,无法发货")
def deliver(self, order):
print("订单已取消,无法送达")
def cancel(self, order):
print("订单已取消,无需再次取消")
class Order:
"""订单 - 上下文"""
def __init__(self, order_id):
self.order_id = order_id
self._state = PendingState()
def set_state(self, state):
"""设置状态"""
self._state = state
print(f"订单 {self.order_id} 状态: {self._state}")
def confirm(self):
"""确认订单"""
self._state.confirm(self)
def ship(self):
"""发货"""
self._state.ship(self)
def deliver(self):
"""送达"""
self._state.deliver(self)
def cancel(self):
"""取消"""
self._state.cancel(self)
# 使用
order = Order("ORD-001")
print("正常流程:")
order.confirm()
order.ship()
order.deliver()
print("\n取消订单:")
order2 = Order("ORD-002")
order2.confirm()
order2.cancel()
print("\n尝试取消已送达订单:")
order.deliver()  # 无法取消

应用2:游戏角色状态

from abc import ABC, abstractmethod
class CharacterState(ABC):
"""角色状态接口"""
@abstractmethod
def move(self, character):
pass
@abstractmethod
def attack(self, character):
pass
@abstractmethod
def defend(self, character):
pass
class NormalState(CharacterState):
"""正常状态"""
def move(self, character):
print(f"{character.name} 正常移动")
character.speed = 10
def attack(self, character):
damage = 20
print(f"{character.name} 攻击,造成 {damage} 点伤害")
return damage
def defend(self, character):
print(f"{character.name} 防御")
character.defense = 5
class PoisonedState(CharacterState):
"""中毒状态"""
def move(self, character):
print(f"{character.name} 中毒,移动速度减半")
character.speed = 5
character.hp -= 2
print(f"{character.name} 中毒伤害: -2 HP")
def attack(self, character):
damage = 15  # 攻击力降低
print(f"{character.name} 中毒攻击,造成 {damage} 点伤害")
character.hp -= 2
return damage
def defend(self, character):
print(f"{character.name} 中毒防御")
character.defense = 3
character.hp -= 2
class FrozenState(CharacterState):
"""冰冻状态"""
def move(self, character):
print(f"{character.name} 被冰冻,无法移动")
character.speed = 0
def attack(self, character):
print(f"{character.name} 被冰冻,无法攻击")
return 0
def defend(self, character):
print(f"{character.name} 冰冻防御")
character.defense = 0
class BoostedState(CharacterState):
"""强化状态"""
def move(self, character):
print(f"{character.name} 移动速度加倍")
character.speed = 20
def attack(self, character):
damage = 30  # 攻击力提升
print(f"{character.name} 强化攻击,造成 {damage} 点伤害")
return damage
def defend(self, character):
print(f"{character.name} 强化防御")
character.defense = 10
class Character:
"""角色 - 上下文"""
def __init__(self, name):
self.name = name
self.hp = 100
self._state = NormalState()
self.speed = 10
self.defense = 5
def set_state(self, state):
"""设置状态"""
self._state = state
print(f"{self.name} 状态: {state.__class__.__name__}")
def move(self):
"""移动"""
self._state.move(self)
def attack(self):
"""攻击"""
return self._state.attack(self)
def defend(self):
"""防御"""
self._state.defend(self)
def take_damage(self, damage):
"""受到伤害"""
actual_damage = max(0, damage - self.defense)
self.hp -= actual_damage
print(f"{self.name} 受到 {actual_damage} 点伤害,剩余 HP: {self.hp}")
def poison(self):
"""中毒"""
self.set_state(PoisonedState())
def freeze(self):
"""冰冻"""
self.set_state(FrozenState())
def boost(self):
"""强化"""
self.set_state(BoostedState())
def cure(self):
"""治疗"""
self.set_state(NormalState())
# 使用
hero = Character("勇者")
print("正常状态:")
hero.move()
hero.attack()
hero.defend()
print("\n中毒状态:")
hero.poison()
hero.move()
hero.attack()
print("\n冰冻状态:")
hero.freeze()
hero.move()
hero.attack()
print("\n强化状态:")
hero.cure()
hero.boost()
hero.move()
hero.attack()
print("\n恢复正常:")
hero.cure()
hero.move()

应用3:文档编辑器状态

from abc import ABC, abstractmethod
class EditorState(ABC):
"""编辑器状态接口"""
@abstractmethod
def type(self, editor, text):
pass
@abstractmethod
def copy(self, editor):
pass
@abstractmethod
def paste(self, editor):
pass
@abstractmethod
def save(self, editor):
pass
class NormalState(EditorState):
"""正常状态"""
def type(self, editor, text):
editor.content += text
print(f"输入: {text}")
def copy(self, editor):
print("复制文本")
def paste(self, editor):
print("粘贴文本")
def save(self, editor):
print("保存文档")
class ReadOnlyState(EditorState):
"""只读状态"""
def type(self, editor, text):
print("❌ 文档只读,无法编辑")
def copy(self, editor):
print("复制文本")
def paste(self, editor):
print("❌ 文档只读,无法粘贴")
def save(self, editor):
print("❌ 文档只读,无法保存")
class AutoSaveState(EditorState):
"""自动保存状态"""
def type(self, editor, text):
editor.content += text
print(f"输入: {text}")
print("📝 自动保存...")
def copy(self, editor):
print("复制文本")
def paste(self, editor):
print("粘贴文本")
print("📝 自动保存...")
def save(self, editor):
print("保存文档")
class TextEditor:
"""文本编辑器 - 上下文"""
def __init__(self):
self.content = ""
self._state = NormalState()
self._clipboard = ""
def set_state(self, state):
"""设置状态"""
self._state = state
print(f"编辑器状态: {state.__class__.__name__}")
def type(self, text):
"""输入"""
self._state.type(self, text)
def copy(self):
"""复制"""
self._state.copy(self)
def paste(self):
"""粘贴"""
self._state.paste(self)
def save(self):
"""保存"""
self._state.save(self)
def set_read_only(self):
"""设置为只读"""
self.set_state(ReadOnlyState())
def set_auto_save(self):
"""设置为自动保存"""
self.set_state(AutoSaveState())
def set_normal(self):
"""设置为正常"""
self.set_state(NormalState())
# 使用
editor = TextEditor()
print("正常状态:")
editor.type("Hello ")
editor.type("World!")
editor.save()
print("\n只读状态:")
editor.set_read_only()
editor.type("Cannot type")
editor.save()
print("\n自动保存状态:")
editor.set_normal()
editor.set_auto_save()
editor.type("Auto save")
editor.type(" enabled")

状态模式 vs 策略模式

维度 状态模式 策略模式
目的 改变行为 算法可互换
转换 状态自动转换 手动选择策略
依赖 状态之间依赖 策略独立
使用场景 状态相关行为 算法替换
graph TB A[模式对比] --> B[状态模式] A --> C[策略模式] B --> B1[行为随状态改变] B --> B2[状态自动转换] B --> B3[状态间有依赖] C --> C1[算法可互换] C --> C2[手动选择策略] C --> C3[策略间独立] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style B fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style C fill:#fff9c4,stroke:#f9a825,stroke-width:2px

优缺点

✅ 优点

优点 说明
消除条件 避免大量if-else
封装状态 每个状态独立
易于扩展 新增状态不影响其他
状态转换清晰 转换逻辑集中在状态类

❌ 缺点

缺点 说明
类数量多 每个状态一个类
状态依赖 状态间可能有依赖
复杂度 简单场景可能过度设计

适用场景

场景 是否适合
行为随状态改变 ✅ 适合
状态转换复杂 ✅ 适合
大量条件判断 ✅ 适合
简单状态切换 ❌ 不适合

本章要点


恭喜完成行为型模式部分!

下一步模式对比与选择 开始综合实践 🚀