状态模式概念
- 一个对象可以基于其内部状态封装多个行为
- 也可以看做在运行时改变对象行为的一种方式(Python正好擅长这一点)
实现
例子:收音机具有AM/FM两种调频方式和一个扫描按钮,扫描可以扫描到多个FM/AM频道。当用户打开,设置为FM。点击扫描,可以扫到多个有效FM频道。如果改变为AM,扫描只会扫到AM频道。
也就是根据频道状态,改变扫描行为。
from abc import ABCMeta, abstractmethod
class State(metaclass=ABCMeta):
@abstractmethod
def handel(self):
pass
class ConcreteStateA(State):
def handel(self):
print('A')
class ConcreteStateB(State):
def handel(self):
print('B')
class Context(State):
def __init__(self):
self.state = None
def get_state(self):
return self.state
def set_state(self, state):
self.state = state
def handel(self):
self.state.handel()
context = Context()
sA = ConcreteStateA()
sB = ConcreteStateB()
context.set_state(sA)
context.handel()
计算机状态例子
假设计算机有4种状态,开机,关机,休眠,挂起。只有开机情况下能切换到其他3种状态,其他三种状态只能切换到开机。利用状态模式实现:
class ComputerState(object):
name = 'state' # 对象状态名称
allowed = [] # 定义允许进入的状态的对象的列表
# 改变计算机的状态的方法
def switch(self, state):
if state.name in self.allowed:
print('现状态:', self, ',转换成', state.name, '成功')
self.__class__ = state
else:
print('现状态:', self, ',转换成', state.name, '失败!!')
def __str__(self):
return self.name
# 关闭
class Off(ComputerState):
name = 'off'
allowed = ['on']
# 打开
class On(ComputerState):
name = 'on'
allowed = ['suspend', 'off', 'hibernate']
# 休眠
class Suspend(ComputerState):
name = 'suspend'
allowed = ['on']
# 挂起
class Hibernate(ComputerState):
name = 'hibernate'
allowed = ['on']
class Computer(object):
# 初始状态
def __init__(self, model='MacBook Pro'):
self.model = model
self.state = Off()
# 改变状态
def change_to(self, state):
self.state.switch(state)
if __name__ == '__main__':
computer = Computer()
computer.change_to(On)
computer.change_to(Off)
computer.change_to(On)
computer.change_to(Suspend)
# 这里不能挂起,必须要转换为on后才可以
computer.change_to(Hibernate)
computer.change_to(On)
computer.change_to(Hibernate)
computer.change_to(On)
computer.change_to(Off)
'''结果
现状态: off ,转换成 on 成功
现状态: on ,转换成 off 成功
现状态: off ,转换成 on 成功
现状态: on ,转换成 suspend 成功
现状态: suspend ,转换成 hibernate 失败!!
现状态: suspend ,转换成 on 成功
现状态: on ,转换成 hibernate 成功
现状态: hibernate ,转换成 on 成功
现状态: on ,转换成 off 成功
'''
状态设计模式优缺点
优点
- 消除了对if/else或者switch的依赖
- 易于添加状态
- 提高聚合性
- 只添加一个ConcreteState类就可以添加行为,提高可维护性
缺点
- 类太多了,每个行为都要写类,结构复杂,代码增加
- 随着新行为(类)的增加,Context都要进行更改,上下文更容易受到新类的影响。