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

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

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


以上所述就是小编给大家介绍的《Design Pattern(7) - State》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Ext JS源码分析与开发实例宝典

Ext JS源码分析与开发实例宝典

彭仁夔 / 电子工业出版社 / 2010-1 / 78.00元

《Ext JS源码分析与开发实例宝典》从Ext JS实现的基本功能开始讲解,从两个方面对Ext JS进行整体上的概述,让读者从宏观上去把握ExtJS框架。接下来讲解Ext JS核心基础知识,包括事件机制、模板模型、数据模型以及对类、函数、字符串、日期、数组及定时任务这6个类进行扩展。然后讲解Ext JS基于元素的开发,包括动画特效和拖曳实现等。最后深入讲解组件的开发,对布局、模型及4大组件一一进行......一起来看看 《Ext JS源码分析与开发实例宝典》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具