狀態機模式非常適合用在複雜的流程或者是系統當中,可以方便我們對系統的某乙個狀態進行抽象,這會讓我們編碼具有更強的可讀性以及延展性。
首先和大家解釋一下狀態機當中這個狀態的概念,這裡的狀態指的是我們系統或者是流程當中的某乙個狀態。我用我之前做過的乙個活動系統來給大家舉乙個例子。
比如我們現在要在網上舉辦一些活動,然後吸引使用者來參與。但是在使用者來參與活動的過程當中其實有很多的狀態需要判斷,比如說我們首先要判斷使用者是否已經登入了。如果登入了,還需要判斷使用者之前是否報名過,如果已經報名了,還需要判斷活動是否開始了等等。
那麼,我們就可以抽象出很多的狀態。比如是否登入、是否報名、未登入等等這些都是狀態。這些狀態之間可以通過一些條件進行轉移,比如在初始狀態當中,通過判斷使用者是否登入選擇轉移到未登入狀態或者是報名判斷的狀態上。我們把這其中的邏輯抽象出來,可以得到這麼一張有向無環圖。
幾乎所有的固定流程都可以抽象出這麼一張圖來,這種圖一般被縮寫成dag(directed acyclic graph)。如果不用狀態機的話,那麼我們需要編寫大量的**來進行判斷。就拿上述的這個邏輯舉例,我們需要至少4層if巢狀的邏輯判斷來實現這麼乙個流程。
如果通過if判斷來實現的話,那麼面臨的乙個問題就是這個流程是固定的。如果臨時需要改動,那麼必須要修改**,而我們知道不管大小公司,發布**都是有嚴格的規範的,是不能隨意發布的。而使用狀態機主要解決的就是這個問題,可以把流程做成可配置的,如果需要臨時修改,只需要修改狀態機的對應配置即可,可以規避掉**層面的修改。
理解了dag之後,我們再來看看狀態機的定義和解釋。
狀態機的官方定義是:
狀態模式會將與狀態有關的邏輯分布寫在代表物件狀態的類中
這句話英文讀起來還是挺好理解的,中文相對更繞一些。簡而言之,machine是一種抽象的概念,代表某乙個流程或者是原理,並不是我們理解的機器。所以狀態機也不是乙個機器,它是由多個代表狀態的類組合而成的流程或者說模式。也就是說我們會把dag當中的每乙個節點(狀態)單獨實現成乙個類,那麼整個dag就是一系列狀態類構成的圖。
對於每個狀態類而言,它們的操作應該都是類似的,就是初始化、執行以及轉移。在一些系統當中,甚至可以沒有執行只有轉移。既然所有狀態的操作都是類似的,那麼我們可以對所有的狀態抽象出統一的介面。這裡我們多了乙個is_end方法,代表某乙個狀態是否是整個流程的結束,如果是的話,我們就不需要繼續轉移了,直接退出即可。
class
state:
def__init__
(states):
pass
defdetermine
(param):
pass
defoperate
():pass
defis_end
():pass
同樣,我們可以實現狀態機的類。
class
statemachine:
def__init__
():self.node = startstate()
definit
():self.node = startstate()
defrun
(param):
while
not self.node.is_end():
self.node = self.node.determine(param)
self.node.operate()
由於狀態之間轉移以及執行的邏輯都被封裝在不同的類當中了,所以對於狀態機而言,裡面的邏輯非常簡單,一般也不需要太大的修改。即使整個流程或者是某乙個狀態的條件發生變動, 我們也只需要修改對應節點的**即可,並不會影響整體,非常適合用在那些流程經常發生變動的場景。
最後,我們來看乙個狀態機的使用案例。這個案例源於github,是乙個將狀態機應用在收音機上的case,具體的細節檢視**即可。
class
state:
defscan
(self):
# 模擬收音機的儀錶盤,只能乙個方向轉動
self.pos += 1
if self.pos == len(self.stations):
self.pos = 0
print('scanning... station is {} {}'.format(self.stations[self.pos], self.name))
class
amstate
(state):
# am 音訊的類
def__init__
(self, radio):
self.radio = radio
self.stations = ['1250', '1380', '1510']
self.pos = 0
self.name = 'am'
deftoggle_amfm
(self):
# 轉移到fm
print('switching to fm')
self.radio.state = self.radio.fmstate
class
fmstate
(state):
# fm 音訊類
def__init__
(self, radio):
self.radio = radio
self.stations = ['81.3', '89.1', '103.9']
self.pos = 0
self.name = 'fm'
deftoggle_amfm
(self):
# 轉移到am
print('switching to am')
self.radio.state = self.radio.amstate
class
radio:
# 收音機的整體類,也就是狀態機類
def__init__
(self):
self.amstate = amstate(self)
self.fmstate = fmstate(self)
self.state = self.amstate
deftoggle_amfm
(self):
self.state.toggle_amfm()
defscan
(self):
self.state.scan()
if __name__ == '__main__':
radio = radio()
actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2
actions *= 2
for action in actions:
action()
整個狀態機的設計模式本身並不複雜,更多的是對這個設計理念和思想的理解,**和形式都是表象。
產品經理的工作流程
產品管理是組織中的乙個重要組成部分,而產品經理在產品管理中扮演著重要的角色。產品經理負責產品的策略 演進路線圖 功能定義等,有些可能還包括市場相關的工作。產品管理源自於品牌管理。在1931年,neil mcelroy在p g的乙份備忘錄提出 品牌經理 的想法,neil作為廣告經理,提出的這個角色需要...
急聘 流程技術顧問, 流程產品售前經理
知名業務流程管理領導廠商美國k2公司 www.k2.com 急聘 流程技術顧問,流程產品售前經理。產品售前經理 負責在銷售過程對客戶進行產品介紹,技術演示,展示解決方案,從技術角度上說服客戶完成銷售。流程技術顧問 負責業務流程梳理,需求調研,流程專案的實施開發以及產品技術支援。如果您熟悉.net技術...
產品經理通用標準工作流程
產品經理最早是1927年由美國保潔公司提出來的概念,彼時保潔負責銷售工作的負責人麥克埃爾洛分析銷售業績不佳的原因,是因為公司同類產品生產銷售各個環節由不同的人負責,這樣容易產生脫節和人力財力浪費的情況。於是他提出了品牌人的概念,乙個品牌人全權負責某個品牌產品的生產經營工作,這樣能夠對產品進行全方位的...