python设计模式【9】-状态模式

  1. UML类图简介
  2. 设计模式的分类
  3. 面向对象的设计原则
  4. python设计模式【1】-单例模式
  5. python设计模式【2】-工厂模式
  6. python设计模式【3】-门面模式
  7. python设计模式【4】-代理模式
  8. python设计模式【5】-观察者模式
  9. python设计模式【6】-命令模式
  10. python设计模式【7】-模板方法模式
  11. python设计模式【8】-模型·视图·控制器-复合模式
  12. python设计模式【9】-状态模式

定义状态设计模式

行为模式关注的是对象的响应性。它们通过对象之间的交互以实现更强大的功能。状态设计模式是一种行为设计模式,有时也被称为状态模式对象。在此模式中,一个对象可以基于其内部状态封装多个行为。状态模式也可以看作是在运行时改变对象行为的一种方式。

状态设计模式允许对象在其内部状态变化时改变其行为。这看起来就像对象本身已经改变了它的类一样。状态设计模式常用于开发有限状态机,并帮助协调状态处理操作。

理解状态设计模式

状态设计模式的三个主要参与者:

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()

状态设计模式简单示例2

例如一个计算机系统,它可以有多个状态;如开机、关机、挂起或休眠。现在想利用状态设计模式来表述这些状态;

首先从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类都需要进行相应的更新处理每个行为。这使得上下文行为更容易受到每个新的行为的影响。


参考:

《python设计模式》(第2版)https://www.epubit.com/

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页