Design Pattern(7) - State

栏目: 后端 · 发布时间: 6年前

内容简介:Design Pattern(7) - State

以下文章是閱讀 深入淺出Design Pattern 還有 聖經 還有 Source making 的筆記 圖片截圖自lynda.com的 Foundations of Programming: Design Patterns 要更深入的理解一定要去看這兩本書

糖果機

一個糖果機會有很多種不同的狀態

Design Pattern(7) - State

一開始在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要全部重寫

但還有一個更重要的原因

Design Pattern(7) - State

我們應該把每一個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

Design Pattern(7) - State

Action裡面的setState 就是剛剛state diagram裡面的箭頭 哪一個狀態遇到哪一個action會變成另外哪個狀態 一目瞭然

今後只要PM有給你定義好的state diagram 你用state pattern實做起來輕輕鬆鬆

狀態模式

讓物件的行為隨著物件的 狀態 產生改變 就好像整個類別改變了一樣

結構

Design Pattern(7) - State

  • 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困難

人的精神有三種境界:駱駝 獅子 嬰兒 第一境界駱駝 忍辱負重 被動地聽命於別人或命運的安排 第二境界獅子 把被動變成主動 由「你應該」到「我要」一切由我主動爭取 主動負起人生責任 第三境界嬰兒 這是一種「我是」的狀態 活在當下 享受現在的一切

尼采 《查拉圖斯特拉如是說》


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

学习JavaScript数据结构与算法

学习JavaScript数据结构与算法

[巴西] 格罗纳(Loiane Groner) / 孙晓博、邓钢、吴双、陈迪、袁源 / 人民邮电出版社 / 2015-10-1 / 39.00

本书首先介绍了JavaScript语言的基础知识,接下来讨论了数组、栈、队列、链表、集合、字典、散列表、树、图等数据结构,之后探讨了各种排序和搜索算法,包括冒泡排序、选择排序、插入排序、归并排序、快速排序、顺序搜索、二分搜索,还介绍了动态规划和贪心算法等常用的高级算法及相关知识。一起来看看 《学习JavaScript数据结构与算法》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具