Python設計模式之狀態模式

狀態模式概念

  • 一個對象可以基於其內部狀態封裝多個行爲
  • 也可以看做在運行時改變對象行爲的一種方式(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都要進行更改,上下文更容易受到新類的影響。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章