Design Pattern(7) - State
May 30, 2017以下文章是閱讀 深入淺出Design Pattern 還有 聖經還有Source making的筆記 圖片截圖自lynda.com的Foundations of Programming: Design Patterns 要更深入的理解一定要去看這兩本書
糖果機
一個糖果機會有很多種不同的狀態
一開始在No Quarter狀態 投錢後跑到Has Quarter 轉一下柄之後就賣糖果給你 賣完後如果裡面還有糖果 就跑回No Quarter 如果沒糖果了 就跑到Sold Out
可是剛剛說的是happy case 但我們其實有各種不同的action(箭頭旁邊的字是action) 圖上面只告訴你valid的action 事實上很多action在不同的state是不允許的
比如說你在Sold或Sold Out的state不能投錢 或是你在No Quarter的state不能轉柄
每個State可以允許的action都不一樣 或是說每個State對於同一個action的behavior不一樣 就好像換了一個class一樣
土法煉鋼的寫法 每個action執行時 先看現在屬於哪個State 再決定動作
相信天知地知你知我知這樣不行
這樣要加一個state或是一個action 裡面的if-else要全部重寫
但還有一個更重要的原因
我們應該把每一個state實作成不同的class 所有可能的action定義成一個interface 並且這些class去實作這個interface
先來看State
State interface定義了每個state需要實作的action
再來看個No Quarter State
每個State裡面定義清楚要做的事 或是transition function
Action裡面的setState 就是剛剛state diagram裡面的箭頭 哪一個狀態遇到哪一個action會變成另外哪個狀態 一目瞭然
今後只要PM有給你定義好的state diagram 你用state pattern實做起來輕輕鬆鬆
狀態模式
讓物件的行為隨著物件的狀態產生改變 就好像整個類別改變了一樣
結構
-
Context(GumballMachine): 制定給外界存取的interface, 持有一個ConcreteState的instance 代表現在的狀態
-
State: 一個interface 定義所有ConcreteState必須實作的行為
-
ConcreteState(NoQuarterState): 針對某一種Context的狀態實作每個可能展現的行為
優缺點
1.封裝了狀態轉換的邏輯 Context委任給給現在的狀態決定行為以及要不要改變狀態
Note: 事實上並沒有規定說一定要讓state自己決定要轉到哪個狀態 這樣其實增加了concreteState彼此的相依性 你也可以把轉換的邏輯定義在Context裡 但這樣就沒有封裝狀態轉換的邏輯
經驗法則是如果State子類別不是很多就用後者 反之用前者
2.用State模式會大量增加class/object的數目
3.跟抽象工廠的問題很像:開閉原則的傾斜性 對於新增State容易 對於新增action困難
人的精神有三種境界:駱駝 獅子 嬰兒 第一境界駱駝 忍辱負重 被動地聽命於別人或命運的安排 第二境界獅子 把被動變成主動 由「你應該」到「我要」一切由我主動爭取 主動負起人生責任 第三境界嬰兒 這是一種「我是」的狀態 活在當下 享受現在的一切
尼采 《查拉圖斯特拉如是說》