内容简介:Design Pattern(7) - State
以下文章是閱讀 深入淺出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 再決定動作
public void insertQuarter() { if (state == HAS_QUARTER) { System.out.println("You can't insert another quarter"); } else if (state == NO_QUARTER) { state = HAS_QUARTER; System.out.println("You inserted a quarter"); } else if (state == SOLD_OUT) { System.out.println("You can't insert a quarter, the machine is sold out"); } else if (state == SOLD) { System.out.println("Please wait, we're already giving you a gumball"); } }
public void turnCrank() { if (state == SOLD) { System.out.println("Turning twice doesn't get you another gumball!"); } else if (state == NO_QUARTER) { System.out.println("You turned but there's no quarter"); } else if (state == SOLD_OUT) { System.out.println("You turned, but there are no gumballs"); } else if (state == HAS_QUARTER) { System.out.println("You turned..."); state = SOLD; dispense(); } }
相信天知地知你知我知這樣不行
這樣要加一個state或是一個action 裡面的if-else要全部重寫
但還有一個更重要的原因
我們應該把每一個state實作成不同的class 所有可能的action定義成一個interface 並且這些class去實作這個interface
先來看State
public interface State { public void insertQuarter(); public void ejectQuarter(); public void turnCrank(); public void dispense(); }
State interface定義了每個state需要實作的action
再來看個No Quarter State
public class NoQuarterState implements State { GumballMachine gumballMachine; public NoQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("You inserted a quarter"); gumballMachine.setState(gumballMachine.getHasQuarterState()); } public void ejectQuarter() { System.out.println("You haven't inserted a quarter"); } public void turnCrank() { System.out.println("You turned, but there's no quarter"); } public void dispense() { System.out.println("You need to pay first"); } public String toString() { return "waiting for quarter"; } }
每個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困難
人的精神有三種境界:駱駝 獅子 嬰兒 第一境界駱駝 忍辱負重 被動地聽命於別人或命運的安排 第二境界獅子 把被動變成主動 由「你應該」到「我要」一切由我主動爭取 主動負起人生責任 第三境界嬰兒 這是一種「我是」的狀態 活在當下 享受現在的一切
尼采 《查拉圖斯特拉如是說》
以上所述就是小编给大家介绍的《Design Pattern(7) - State》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
两周自制脚本语言
[日]千叶 滋 / 陈筱烟 / 人民邮电出版社 / 2014-6 / 59.00元
《两周自制脚本语言》是一本优秀的编译原理入门读物。全书穿插了大量轻松风趣的对话,读者可以随书中的人物一起从最简单的语言解释器开始,逐步添加新功能,最终完成一个支持函数、数组、对象等高级功能的语言编译器。本书与众不同的实现方式不仅大幅简化了语言处理器的复杂度,还有助于拓展读者的视野。 《两周自制脚本语言》适合对编译原理及语言处理器设计有兴趣的读者以及正在学习相关课程的大中专院校学生。同时,已经......一起来看看 《两周自制脚本语言》 这本书的介绍吧!