定義狀態設計模式
行爲模式關注的是對象的響應性。它們通過對象之間的交互以實現更強大的功能。狀態設計模式是一種行爲設計模式,有時也被稱爲狀態模式對象。在此模式中,一個對象可以基於其內部狀態封裝多個行爲。狀態模式也可以看作是在運行時改變對象行爲的一種方式。
狀態設計模式允許對象在其內部狀態變化時改變其行爲。這看起來就像對象本身已經改變了它的類一樣。狀態設計模式常用於開發有限狀態機,並幫助協調狀態處理操作。
理解狀態設計模式
狀態設計模式的三個主要參與者:
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類都需要進行相應的更新處理每個行爲。這使得上下文行爲更容易受到每個新的行爲的影響。