前言
行为模式关注的是对象的响应性,它们通过对象之间的交互以实现更强大的功能。 状态设计模式也是一种行为模式。
1. 状态设计模式的定义
在状态模式中,一个对象可以基于其内部状态封装多个行为,可以看作是在运行改变对象行为的一种方式。
举个例子:收音机具有AM/FM两种调频方式和一个扫描按钮,该按钮可以扫描多个FM/AM频道。它的基本状态已经设定好了,如设为FM,这个时候单 击扫描按钮可以将收音机调谐到多个有效的FM频率或频道。当状态改为AM时,扫描按钮则会帮助用户调谐到多个AM频道。根据AM、FM两种状态来相 应地改变状态。
2. 状态设计模式的组成部分
- State:被认为是封装对象行为的接口,这个行为与对象的状态相关联。
- ConcreteState:实现State接口的子类,实现与对象的特定状态相关联的实际行为。
- Context:定义了客户感兴趣的接口,维护一个ConcreteState子类的实例,该子类在内部定义了对象的特定状态的实现。
简单代码表示如下,其中Handle()抽象方法为状态接口:
from abc import abstractmethod, ABCMeta
class State(metaclass=ABCMeta):
@abstractmethod
def Handle(self):
pass
class ConcreteStateB(State):
def Handle(self):
print("ConcreteStateB")
class ConcreteStateA(State):
def Handle(self):
print("ConcreteStateA")
class Context(State):
def __init__(self):
self.state = None
def getState(self):
return self.state
def setState(self, state):
self.state = state
def Handle(self):
self.state.Handle()
context = Context()
stateA = ConcreteStateA()
stateB = ConcreteStateB()
context.setState(stateA)
context.Handle()
context.setState(stateB)
context.Handle()
3. 状态设计模式实例:电视机开关
直接上代码了,其实与上述简单代码类似:
from abc import abstractmethod, ABCMeta
class State(metaclass=ABCMeta):
@abstractmethod
def doThis(self):
pass
class StartState(State):
def doThis(self):
print("TV Switching ON..")
class StopState(State):
def doThis(self):
print("TV Switching OFF..")
class TVContext(State):
def __init__(self):
self.state = None
def getState(self):
return self.state
def setState(self, state):
self.state = state
def doThis(self):
self.state.doThis()
context = TVContext()
context.getState()
start = StartState()
stop = StopState()
context.setState(stop)
context.doThis()
4. 状态设计模式实例:计算机系统开关机、休眠和挂起
首先是定义计算机状态类ComputerState接口,包含属性name和allowed,name表示对象的状态,allowed表示允许进入的状态的对象的列表。 然后还要包含一个switch()方法,来实际改变对象的状态,其中用到__class__可以实现对类的引用,如 self.__class__.__name__可以调用类的名称。
接着是四种ConcreteState类,实现State接口,即:
- On:打开计算机,允许Off、Suspend和Hibernate状态。
- Off:关闭计算机,允许On状态。
- Hibernate:休眠模式,允许On状态。
- Suspend:挂起模式,允许On状态。
最后实现Context类,也就是计算机,一个是初始化方法,定义计算机的基本状态,另一个是change()方法,用来改变对象的状态,但是实际上是 调用了ConcreteState类实现的。
具体代码如下:
class ComputerState(object):
name = "state"
allowed = []
def switch(self, state):
if state.name in self.allowed:
print('Current:', self, '=> switched to new state', state.name)
self.__class__ = state
else:
print('Current:', self, '=> switching to', state.name, 'not possible.')
def __str__(self):
return self.name
class Off(ComputerState):
name = "off"
allowed = ['on']
class On(ComputerState):
name = "on"
allowed = ['off', 'suspend', 'hibernate']
class Suspend(ComputerState):
name = "suspend"
allowed = ['on']
class Hibernate(ComputerState):
name = "hibernate"
allowed = ['on']
class Computer(object):
def __init__(self, model='HP'):
self.model = model
self.state = Off()
def change(self, state):
self.state.switch(state)
if __name__ == "__main__":
comp = Computer()
# State on
comp.change(On)
# Switch off
comp.change(Off)
# Switch on again
comp.change(On)
# Suspend
comp.change(Suspend)
# Try to hibernate - cannot!
comp.change(Hibernate)
# switch on back
comp.change(On)
# Finally off
comp.change(Off)
执行了上述代码会有如下结果:
shell script
Current: off => switched to new state on
Current: on => switched to new state off
Current: off => switched to new state on
Current: on => switched to new state suspend
Current: suspend => switching to hibernate not possible.
Current: suspend => switched to new state on
Current: on => switched to new state off
5. 状态设计模式的优缺点
优点:
- 对象的行为是其状态的函数结果,并且行为在运行时根据状态而改变,这可以消除对if-else或switch-case条件逻辑的依赖。
- 使用状态模式,更易于添加状态来支持额外的行为。
- 状态设计模式提高了聚合性,因为特定于状态的行为被聚合到ConcreteState类中,并且放置在代码中的同一个地方。
- 通过只添加一个ConcreteState类来添加行为是非常容易的,因此状态模式盖上了扩展应用程序行为时的灵活性,而且全面提高了代码的可维护 性。
不足:
- 类爆炸:可能导致创建了太多功能较为单一的类,增加了代码量,又使得状态结构更加难以审查。
- 随着每个新行为的引入,Context类都需要进行相应的更新以处理每个行为,使得上下文行为更容易受到每个新的行为的影响。
后记
小结一下:
- 对象的行为是根据它的状态来决定的,在运行时改变对象。
- Context类为客户端提供了一个更加简单的接口,同时ConcreteState能够让向对象添加行为变得更加容易。
- 状态设计模式提高了内聚性,易于扩展,还能清除冗余代码块,但同时也有缺陷,可能代码的数量会增加。
下一章是反模式。