狀態模式概念
- 一個對象可以基於其內部狀態封裝多個行爲
- 也可以看做在運行時改變對象行爲的一種方式(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都要進行更改,上下文更容易受到新類的影響。