状态模式的核心是让状态对象自主决定行为并封装状态切换逻辑,主类仅持state属性并委托调用;需用abc.abc定义统一接口,避免方法名不一致导致attributeerror;状态切换必须由状态自身触发,而非外部硬编码赋值;状态少于3种时推荐字典映射等轻量方案。

状态模式的核心不是写更多类,而是让状态自己决定行为
直接用状态对象替代 if-else 分支判断,关键在于把“当前状态该做什么”这件事从主类里剥离出去。主类只保留一个 state 属性,所有行为委托给它;每个状态子类实现自己的 handle() 或具体方法(比如 press()、pull()),不再由主类判断“如果是打开状态就执行A,关闭状态就执行B”。
用抽象基类定义状态接口,避免运行时 AttributeError
Python 没有强制接口语法,但必须提前约定方法签名,否则调用时才发现某个状态漏实现 press(),就会抛出 AttributeError。推荐用 abc.ABC 和 @abstractmethod 声明契约:
from abc import ABC, abstractmethod <p>class LightState(ABC): @abstractmethod def press(self, context): pass</p>
常见错误:直接用普通父类或空类做基类,导致不同状态实现方法名不一致(比如一个叫 on(),另一个叫 toggle()),主类调用时崩溃。
状态切换必须由状态自己触发,不能由外部硬编码赋值
主类(如 LightSwitch)不该写 self.state = OnState() 这类逻辑——这会让状态流转逻辑散落在各处,违背模式初衷。正确做法是:每个状态的 press() 方法内部决定下一步该切到哪个状态,并主动更新上下文的 state:
-
OnState.press()里调用context.state = OffState() -
OffState.press()里调用context.state = OnState() - 上下文(
context)只需提供state属性的读写权限,不参与决策
容易踩的坑:在主类里根据条件判断后手动切换状态,等于把 if-else 从方法里挪到了状态切换处,没真正解耦。
避免过度设计:状态少于3种时,用字典映射更轻量
如果只有开/关两种状态,且行为极其简单(比如只是打印一行日志),硬套状态模式反而增加5个文件和4层跳转。此时用字典驱动更直接:
states = {
'off': lambda: print('turning on'),
'on': lambda: print('turning off')
}
# 调用:states[current_state]()
状态模式真正的价值出现在:状态数 ≥3、状态间转移条件复杂(比如“长按3秒进入配网态”)、或不同状态下同一操作语义完全不同(如编辑器中“Ctrl+Z”在文本态撤销,在选区态取消选择)。这时候才值得引入类结构。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











