行为模式关注的是对象的响应性。它们通过对象之间的交互以实现更强大的功能。状态设计模式是一种行为设计模式,有时也被称为状态模式对象。在此模式中,一个对象可以基于其内部状态封装多个行为。状态模式也可以看作是在运行时改变对象行为的一种方式。
状态设计模式允许对象在其内部状态变化时改变其行为。这看起来就像对象本身已经改变了它的类一样。状态设计模式常用于开发有限状态机,并帮助协调状态处理操作。
状态设计模式的三个主要参与者:
1、State:这被认为是封装对象行为的接口。这个行为与对象的状态相关联。
2、ConcreteState:这是实现State接口的子类。ConcreteState实现对象的特定状态相关联的实际行为
3、Context:这定义了客户感兴趣的接口。Context还维护一个ConcreteState子类的实例,该子类在内部定义了对象的特定状态的实现
下面我们来考察带有上述3个参与者的状态设计模式的结构代码实现:
from abc import ABCMeta, abstractmethod
class State(metaclass=ABCMeta):
@abstractmethod
def handle(self):
pass
class ConcreteStateA(State):
def handle(self):
print("ConcreteStateA")
class ConcreteStateB(State):
def handle(self):
print("ConcreteStateB")
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 handle(self):
self.state.handle()
context = Context()
stateA = ConcreteStateA()
stateB = ConcreteStateB()
context.set_state(stateA)
context.handle()
下面的代码实现电视遥控器的开关按钮:
from abc import abstractmethod, ABCMeta
class State(metaclass=ABCMeta):
@abstractmethod
def do_this(self):
pass
class StartState(State):
def do_this(self):
print("TV on")
class StopState(State):
def do_this(self):
print("TV off")
class TVContext(State):
def __init__(self):
self.state = None
def set_state(self, state):
self.state = state
def get_state(self):
return self.state
def do_this(self):
self.state.do_this()
context = TVContext()
context.get_state()
start = StartState()
stop = StopState()
context.set_state(stop)
context.do_this()
例如一个计算机系统,它可以有多个状态;如开机、关机、挂起或休眠。现在想利用状态设计模式来表述这些状态;
首先从ComputerState接口开始:
1、state应定义两个属性,它们是name和allowed。属性name表示对象的状态,而属性allowed是定义允许进入状态的对象的列表
2、state必须定义一个switch()方法,由它来实际改变对象的状态
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)
else:
print('Current:', self, '=>switched to', state.name, 'not possible')
def __str__(self):
return self.name
下面实现State接口的ConcreteState,我们定义了四个状态
1、 On:这将打开计算机。这时候允许的状态是Off、Suspend和Hibernate。
2、Off:这将关闭计算机。这时候允许的状态只有On
3、Hibernate:该状态将计算机置于休眠模式。当计算机处于这种状态时,只能执行打开操作
4、Suspend:该状态将使计算机挂起,一旦计算机挂起,就可以执行打开操作
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']
现在考虑context类,上下文需要做两个主要的事情:
1、__init__():该方法定义了计算机的基本状态。
2、change():该方法将更改对象的状态,但是行为的实际更改是由ConcreteState类实现的
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()
comp.change(On)
comp.change(Off)
comp.change(On)
comp.change(Suspend)
comp.change(Hibernate)
comp.change(On)
comp.change(Off)
1、在状态设计模式中,对象的行为是其状态的函数结果,并且行为在运动时根据状态而改变。这消除了if/else或switch/case条件逻辑的依赖。
2、使用状态模式,实现多态行为的好处显而易见的,并且更易于添加状态来支持额外的行为
3、状态设计还提高了聚合性,因为特定于状态的行为被聚合到ConcreteState类中,并且放置在代码中的同一个地方
4、使用状态设计模式,通过只添加一个ConcreteState类来添加行为是非常容易的。因此,状态模式不仅改善了扩展应用程序行为时的灵活性,而且全面提高了代码的可维护性。
1、类爆炸:由于每个状态都需要在ConcreteState的帮助下定义,因此我们可能导致创建了太多功能比较单一的类。我们不妨考虑有限状态机的情况——如果有许多状态,但是每个状态与另一个状态没有太大的不同,我们仍然需要将它们写成单独的ConcreteState类。这即增加了代码量,又使得状态机构更加难以审查。
2、随着每个新行为的引入,Context类都需要进行相应的更新处理每个行为。这使得上下文行为更容易受到每个新的行为的影响。