状态模式可以看作是在运行时改变对象行为的一种方式。
假设有一台笔记本电脑,它有以下几个状态:
- 开机「On」
- 关机「Off」
- 挂起「Suspend」
- 休眠「Hibernate」
封装对象行为的接口
首先需要一个行为与对象状态关联的接口
它有两个属性:
- 状态
- 允许的状态
它有一个方法:
- 切换状态
切换状态的时候会使用self.__class__
将它动态切换到状态对应的对象,这个稍后再看。
class ComputerState(object):
name = "状态"
allowed = []
def switch(self, state):
if state.name in self.allowed:
print(f"状态由「{self}」切换到新的状态「{state.name}」。")
self.__class__ = state
else:
print(f"状态由「{self}」切换到新的状态{state.name}是不可能的。")
def __str__(self):
return self.name
定义几种状态
- name对应当前类的状态
- allowed对应当前状态支持的转换状态
class Off(ComputerState):
name = '关闭'
allowed = ['打开']
class On(ComputerState):
name = '打开'
allowed = ['关闭', '休眠', '挂起']
class Suspemd(ComputerState):
name = '挂起'
allowed = ['打开']
class Hibernate(ComputerState):
name = '休眠'
allowed = ['打开']
定义一个计算机
代码语言:javascript复制class Computer(object):
def __init__(self):
self.state = Off()
def change(self, state):
self.state.switch(state)
一个计算机的初始状态就是关机状态咯,所以实例化的时候把Off()
赋给self.state
测试
代码语言:javascript复制if __name__ == '__main__':
computer = Computer()
computer.change(On)
computer.change(Off)
computer.change(On)
computer.change(Suspemd)
computer.change(Hibernate)
computer.change(On)
computer.change(Off)
实例化一下之后,
- 开机
- 关机
- 开机
- 挂起
- 休眠
- 开机
- 关机
运行结果
self.class
可以通过调试模式来进行学习
将断点创建在self.__class__ = state
这一行上
可以看到等号左侧是Off
,右侧是On
,这样就完成了状态的切换。
状态1
状态2
优缺点
优点
- 取消了if/else条件逻辑的依赖
- 方便添加状态来支持额外的行为
- 提高聚合性
- 非常容易的添加行为,提高了代码的灵活性,提高了代码的可维护性
缺点:
- 类太多了,
- 新行为引入,其他子类都需相应的处理该新行为。这样使得上下文更容易受到每个新的行为的影响。