日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

《Head First 设计模式》第十章-状态模式 状态模式

發(fā)布時間:2023/12/13 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Head First 设计模式》第十章-状态模式 状态模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

狀態(tài)模式

策略模式和狀態(tài)模式是雙胞胎,在出生時才分開。你已經(jīng)知道,策略模式是圍繞可以互換的算法來創(chuàng)建成功業(yè)務的,然而,狀態(tài)走的是更崇高的路,它通過改變對象內(nèi)部的狀態(tài)來幫助對象控制自己的行為。

定義狀態(tài)模式

先看看定義:狀態(tài)模式允許對象在內(nèi)部狀態(tài)改變時改變它的行為,對象看起來好像修改了它的類

例題

自動糖果售賣機,糖果機的控制器需要的工作流程如下圖

從上面的狀態(tài)圖中可以找到所有的狀態(tài):

我們可以創(chuàng)建一個實例變量來持有目前的狀態(tài),然后定義每個狀態(tài)的值:

1

2

3

4

5

6

7

//每個狀態(tài)用不同的值表示

final static int SOLD_OUT=0;//售罄

final static int NO_QUARTER=1;//沒有投幣

final static int HAS_QUARTER=2;//已投幣

final static int SOLD=3;//售出糖果

//實例變量持有當前狀態(tài),只要改變變量值狀態(tài)也會隨之改變

int state =SOLD_OUT;

現(xiàn)在,我們將所有系統(tǒng)中可以發(fā)生的動作整合起來:
“投入25分錢”,“退回25分錢”,“轉(zhuǎn)動曲柄”,“發(fā)放糖果”
這些動作是糖果機的接口,這是你能對糖果機做的事情,
調(diào)用任何一個動作都會造成狀態(tài)的轉(zhuǎn)換,
發(fā)放糖果更多是糖果機的內(nèi)部動作,機器自己調(diào)用自己。

我們創(chuàng)建一個類,它的作用就像是一個狀態(tài)機,每一個動作,我們都創(chuàng)建了一個對應的方法,這些方法利用條件語句來決定在每個狀態(tài)內(nèi)什么行為是恰當?shù)摹1热鐚Α巴度?5分錢”這個動作來說,我們可以把對應方法寫成下面的樣子:

1

2

3

4

5

6

7

8

9

10

11

12

13

public void insertQuarter(){

????if(state==HAS_QUARTER){

????????//每個狀態(tài)對應的行為

?????????......

????}else if(state==SOLD_OUT){

????????......

????}else if(state ==SOLD){

????????......

????}else if(state==NO_QUARTER){

????????state=HAS_QUARTER;//狀態(tài)轉(zhuǎn)換

????????......

????}

}

初步代碼

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

class GumballMachine{

????final static int SOLD_OUT=0;

????final static int NO_QUARTER=1;

????final static int HAS_QUARTER=2;

????final static int SOLD=3;

????int state =SOLD_OUT;

????int count =0;//存儲糖果數(shù)量

????public? GumballMachine(int count){

????????this.count=count;

????????if(count>0){

????????????state=NO_QUARTER;

????????}

????}

????//當有25分錢投入,就會執(zhí)行這個方法

????public void insertQuarter(){

????????if(state==HAS_QUARTER){

????????????System.out.println("如果已投入過25分錢,我們就告訴顧客");

????????}else if(state==NO_QUARTER){

????????????state=HAS_QUARTER;

????????????System.out.println("如果是在“沒有25分錢”的狀態(tài)下,我們就接收25分錢," +"并將狀態(tài)轉(zhuǎn)換到“有25分錢”的狀態(tài)");

????????}else if(state ==SOLD_OUT){

????????????System.out.println("如果糖果已經(jīng)售罄,我們就拒絕收錢");

????????}else if(state==SOLD){

????????????System.out.println("如果顧客剛才買了糖果,就需要稍等一下,好讓狀態(tài)轉(zhuǎn)換完畢。" +"恢復到“沒有25分錢”的狀態(tài)");

????????????state=NO_QUARTER;

????????}

????}

????//如果顧客試著退回25分錢就執(zhí)行這個方法

????public void ejectQuarter(){

????????if(state==HAS_QUARTER){

????????????System.out.println("如果有25分錢,我們就把錢退出來,回到“沒有25分錢”的狀態(tài)");

????????????state=NO_QUARTER;

????????}else if(state==NO_QUARTER){

????????????System.out.println("如果沒有25分錢的話,當然不能退出25分錢");

????????}else if(state ==SOLD){

????????????System.out.println("顧客已經(jīng)轉(zhuǎn)動曲柄就不能再退錢了,他已經(jīng)拿到糖果了");

????????}else if(state==SOLD_OUT){

????????????System.out.println("如果糖果售罄,就不能接受25分錢,當然也不可能退錢");

????????}

????}

????//顧客試著轉(zhuǎn)動曲柄

????public void turnCrank(){

????????if(state==SOLD){

????????????System.out.println("別想騙過機器拿兩次糖果");

????????}else if(state==NO_QUARTER){

????????????System.out.println("我們需要先投入25分錢");

????????}else if(state ==SOLD_OUT){

????????????System.out.println("我們不能給糖果,已經(jīng)沒有任何糖果了");

????????}else if(state==HAS_QUARTER){

????????????System.out.println("成功,他們拿到糖果了," +"改變狀態(tài)到“售出糖果”然后調(diào)用機器的disoense()方法");

????????????state=SOLD;

????????????dispense();

????????}

????}

????//調(diào)用此方法,發(fā)放糖果

????public void dispense(){

????????if(state==SOLD){

????????????System.out.println("我們正在“出售糖果”狀態(tài),給他們糖果");

????????????count=count-1;

????????????/*

????????????我們在這里處理“糖果售罄”的情況,如果這是最后一個糖果,將機器的狀態(tài)設(shè)置到“糖果售罄”否則就回到“沒有25分錢”的狀態(tài)

?????????????*/

????????????if(count==0){

????????????????System.out.println();

????????????????state=SOLD_OUT;

????????????}else{

????????????????state=NO_QUARTER;

????????????}

????????}else if(state==SOLD_OUT){

????????????System.out.println("這些都不應該發(fā)生,但是如果做了,就得到錯誤提示");

????????}else if(state ==HAS_QUARTER){

????????????System.out.println("這些都不應該發(fā)生,但是如果做了,就得到錯誤提示");

????????}else if(state==NO_QUARTER){

????????????System.out.println("這些都不應該發(fā)生,但是如果做了,就得到錯誤提示");

????????}

????}

}

盡管程序完美運行,但還是躲不掉需求變更的命運

現(xiàn)在糖果公司要求:當曲柄被轉(zhuǎn)動時,有10%的幾率掉下來的是兩個糖果。(氪金扭蛋)

再回看一下我們的初步代碼,想要實現(xiàn)新的需求將會變得非常麻煩:

  • 必須新增一個中獎的“贏家”狀態(tài)。
  • 必須在每一個方法添加新的判斷條件來處理“贏家”狀態(tài)。
  • 轉(zhuǎn)動把手的方法中還需要檢查目前狀態(tài)是否是“贏家”再決定切換到“贏家”狀態(tài)行為還是正常出售行為。

在現(xiàn)有代碼基礎(chǔ)上做增加將會很麻煩,也不利與以后的維護,擴展性差。

回顧一下第一章的策略模式中的設(shè)計原則:

找出應用中可能需要變化之處,把他們獨立出來

將狀態(tài)獨立出來,封裝成一個類,都實現(xiàn)State接口,類圖如下:

新的設(shè)計想法如下:

  • 首先,我們定義一個State接口,在這個接口內(nèi),糖果機的每個動作都有一個對應的方法
  • 然后為機器的每個狀態(tài)實現(xiàn)狀態(tài)類,這些類將負責在對應的狀態(tài)下進行機器的行為
  • 最后,我們要擺脫舊的條件代碼,取而代之的方式是,將動作委托到狀態(tài)類
  • 代碼

    定義一個State接口

    1

    2

    3

    4

    5

    6

    public interface State {

    ????public void insertQuarter();//投幣

    ????public void ejectQuarter();//退幣

    ????public void turnCrank();//轉(zhuǎn)動出貨把手

    ????public void dispense();//出售

    }

    為機器的每個狀態(tài)實現(xiàn)狀態(tài)類:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    //未投幣狀態(tài)

    public class NoQuarterState?implements State {

    ????GumballMachine gumballMachine;

    ????public NoQuarterState(GumballMachine gumballMachine) {

    ????????this.gumballMachine=gumballMachine;

    ????}

    ????public void insertQuarter() {

    ????????System.out.println("你投入一枚硬幣");

    ????????gumballMachine.setState(gumballMachine.getHasQuarterState());//狀態(tài)轉(zhuǎn)換為已投幣狀態(tài)

    ????}

    ????public void ejectQuarter() {

    ????????System.out.println("你未投幣,無法退錢");

    ????}

    ????public void turnCrank() {

    ????????System.out.println("未投幣,請先投幣");

    ????}

    ????public void dispense() {

    ????????System.out.println("請先投幣");

    ????}

    }

    ?

    //已投幣狀態(tài)

    public class HasQuarterState?implements State {

    ????Random randomWinner=new Random(System.currentTimeMillis());

    ????GumballMachine gumballMachine;

    ????public HasQuarterState(GumballMachine gumballMachine) {

    ????????this.gumballMachine=gumballMachine;

    ????}

    ????public void insertQuarter() {

    ????????System.out.println("已投幣,無法再接收投幣");

    ????}

    ????public void ejectQuarter() {

    ????????System.out.println("已退幣");

    ????????gumballMachine.setState(gumballMachine.getNoQuarterState());

    ????}

    ????public void turnCrank() {

    ????????System.out.println("已轉(zhuǎn)動把手,糖果出售中。。。。");

    ????????int winner=randomWinner.nextInt(10);//隨機數(shù)生成,用以標記“贏家”狀態(tài)

    ????????if((winner==0)&&(gumballMachine.getCount()>1))

    ????????????gumballMachine.setState(gumballMachine.getWinnerState());

    ????????else

    ????????????gumballMachine.setState(gumballMachine.getSoldState());

    ????}

    ????public void dispense() {

    ????????System.out.println("機器中已經(jīng)沒有糖果可以出售了!");

    ????}

    }

    ?

    //出售狀態(tài)

    public class SoldState?implements State {

    ????GumballMachine gumballMachine;

    ????public SoldState(GumballMachine gumballMachine) {

    ????????this.gumballMachine=gumballMachine;

    ????}

    ????public void insertQuarter() {

    ????????System.out.println("請等候,正在初始化機器中");

    ????}

    ????public void ejectQuarter() {

    ????????System.out.println("抱歉,您已轉(zhuǎn)動把手獲得了糖果,無法退幣");

    ????}

    ????public void turnCrank() {

    ????????System.out.println("您重復轉(zhuǎn)動把手,無法再獲取更多糖果");

    ????}

    ????public void dispense() {

    ????????gumballMachine.releaseBall();//出貨,糖果-1

    ????????if(gumballMachine.getCount()>0)

    ????????????gumballMachine.setState(gumballMachine.getNoQuarterState());

    ????????else {

    ????????????System.out.println("糖果已售完");

    ????????????gumballMachine.setState(gumballMachine.getSoldOutState());

    ????????}???

    ????}

    }

    ?

    //售罄狀態(tài)

    public class SoldOutState?implements State {

    ????GumballMachine gumballMachine;

    ????public SoldOutState(GumballMachine gumballMachine) {

    ????????this.gumballMachine=gumballMachine;

    ????}

    ????public void insertQuarter() {

    ????????System.out.println("此機器的糖果已售完,不接收投幣");

    ????}

    ????public void ejectQuarter() {

    ????????System.out.println("未投幣,退幣失敗");

    ????}

    ????public void turnCrank() {

    ????????System.out.println("糖果已售完,轉(zhuǎn)動把手也不會有糖果出來的");

    ????}

    ????public void dispense() {

    ????????System.out.println("機器中已無糖果");

    ????}

    }

    ?

    //贏家狀態(tài)

    public class WinnerState?implements State {

    ????GumballMachine gumballMachine;

    ????public WinnerState(GumballMachine gumballMachine) {

    ????????this.gumballMachine=gumballMachine;

    ????}

    ????public void insertQuarter() {

    ????????System.out.println("請等候,正在初始化機器中");

    ????}

    ????public void ejectQuarter() {

    ????????System.out.println("抱歉,您已轉(zhuǎn)動把手獲得了糖果");

    ????}

    ????public void turnCrank() {

    ????????System.out.println("您重復轉(zhuǎn)動把手,無法再獲取更多糖果");

    ????}

    ????public void dispense() {

    ????????System.out.println("恭喜你成為幸運兒,你將額外獲得一個免費糖果");

    ????????gumballMachine.releaseBall();//出貨,糖果-1

    ????????if(gumballMachine.getCount()==0)

    ????????????gumballMachine.setState(gumballMachine.getSoldOutState());

    ????????else {

    ????????????gumballMachine.releaseBall();

    ????????????if(gumballMachine.getCount()>0)

    ????????????????gumballMachine.setState(gumballMachine.getNoQuarterState());

    ????????????else {

    ????????????????System.out.println("糖果已售完");

    ????????????????gumballMachine.setState(gumballMachine.getSoldOutState());

    ????????????}

    ????????}

    ????}

    }

    糖果機類:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    public class GumballMachine {

    ????State soldOutState;

    ????State noQuarterState;

    ????State hasQuarterState;

    ????State soldState;

    ????State winnerState;

    ?

    ????State state=soldOutState;

    ????int count=0;

    ?

    ????public GumballMachine(int numberGumballs) {//初始化

    ????????soldOutState=new SoldOutState(this);

    ????????noQuarterState=new NoQuarterState(this);

    ????????hasQuarterState=new HasQuarterState(this);

    ????????soldState=new SoldState(this);

    ????????winnerState=new WinnerState(this);

    ?

    ????????this.count=numberGumballs;

    ????????if(numberGumballs>0)

    ????????????state=noQuarterState;//先判斷條件再改變狀態(tài)

    ????}

    ????//將動作委托到狀態(tài)類

    ????public void insterQuarter() {

    ????????state.insertQuarter();

    ????}

    ????public void ejectQuarter() {

    ????????state.ejectQuarter();

    ????}

    ????public void turnCrank() {

    ????????state.turnCrank();

    ????????state.dispense();

    ????}

    ????//獲取當前狀態(tài)

    ????public State getHasQuarterState() {

    ????????return hasQuarterState;

    ????}

    ????//改變狀態(tài)

    ????public void setState(State state) {

    ????????this.state=state;

    ????}

    ????public void releaseBall() {

    ????????System.out.println("糖果從出口售出");

    ????????if(count!=0)

    ????????????count-=1;

    ????}

    ????public State getSoldOutState() {

    ????????return soldOutState;

    ????}

    ????public State getNoQuarterState() {

    ????????return noQuarterState;

    ????}

    ????public State getSoldState() {

    ????????return soldState;

    ????}

    ????//獲取糖果機中糖果數(shù)量

    ????public int getCount() {

    ????????return count;

    ????}

    ?

    ????public State getWinnerState() {

    ????????return winnerState;

    ????}

    ????public String toString() {

    ????????// TODO 自動生成的方法存根

    ????????String s="剩余糖果:"+count;

    ????????return s;

    ????}

    }

    以上就是用狀態(tài)模式實現(xiàn)的,仔細觀察你會發(fā)現(xiàn)狀態(tài)模式其實和策略模式很像,來看看狀態(tài)模式的類圖:

    狀態(tài)模式的類圖其實和策略模式完全一樣!

    狀態(tài)模式與策略模式

    這兩個模式的差別在于它們的“意圖”

    • 以狀態(tài)模式而言,我們將一群行為封裝在狀態(tài)對象中,context的行為隨時可委托到那些狀態(tài)對象中的一個,隨著時間而流逝,當前狀態(tài)在狀態(tài)對象集合中游走改變,以反映出context內(nèi)部的狀態(tài),因此,context的行為也會跟著改變,但是context的客戶對于狀態(tài)對象了解不多,甚至根本是渾然不覺。
    • 以策略模式而言,客戶通常主動指定Context所要組合的策略對象時哪一個。現(xiàn)在,固然策略模式讓我們具有彈性,能夠在運行時改變策略,但對于某個context對象來說,通常都只有一個最適當?shù)牟呗詫ο蟆?/li>
    • 一般的,我們把策略模式想成是除了繼承之外的一種彈性替代方案,如果你使用繼承定義了一個類的行為,你將被這個行為困住,是指要修改它都很難,有了策略模式,你可以通過組合不同的對象來改變行為。
    • 我們把狀態(tài)模式想成是不用在context中放置許多條件判斷的替代方案,通過將行為包裝進狀態(tài)對象中,你可以通過在context內(nèi)簡單地改變狀態(tài)對象來改變context的行為。

    模式區(qū)分

    狀態(tài)模式:封裝基于狀態(tài)的行為,并將行為委托到當前狀態(tài)

    策略模式:將可以互換的行為封裝起來。然后使用委托的方法,覺得使用哪一個行為

    模板方法模式:由子類決定如何實現(xiàn)算法中的某些步驟

    要點

    (1)狀態(tài)模式允許一個對象基于內(nèi)部狀態(tài)而擁有不同的行為。

    (2)和程序狀態(tài)機(PSM)不同,狀態(tài)模式用類來表示狀態(tài)。

    (3)Context會將行為委托給當前狀態(tài)對象。

    (4)通過將每一個狀態(tài)封裝進一個類,我們把以后需要做的任何改變局部化了。

    (5)狀態(tài)模式和策略模式有相同的類圖,但是他們的意圖不同。

    (6)策略模式通常會用行為或算法配置Context類。

    (7)狀態(tài)模式允許Context隨著狀態(tài)的改變而改變行為。

    (8)狀態(tài)轉(zhuǎn)換可以有State類或Context類控制。

    (9)使用狀態(tài)模式通常會導致設(shè)計中類的數(shù)目大量增加。

    (10)狀態(tài)欄可以被多個Context實例共享。

    總結(jié)

    以上是生活随笔為你收集整理的《Head First 设计模式》第十章-状态模式 状态模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 激情视频免费观看 | 午夜寂寞视频 | 91网站在线观看视频 | 99精品视频99| 久久综合干 | 久久不卡 | 久久久久久久久久网站 | 图片区亚洲色图 | 日本中文字幕在线播放 | 在线伊人 | 四虎黄色网 | www.av欧美 | 黑人巨大精品欧美黑白配亚洲 | 色视频网 | 91国模少妇一区二区三区 | 新av在线 | 国产成人综合在线视频 | 好爽…又高潮了毛片免费看 | 国产理论 | 碰在线视频 | 日韩一区二区三区电影 | 欧美婷婷 | 黄色成人在线视频 | 五月天在线播放 | 婷婷国产| 成人aaa视频 | 精品国产午夜福利 | 欧美视频1区 | 中文字幕制服诱惑 | 精品黑人一区二区三区观看时间 | 中文字幕人妻一区二 | 亚洲综合黄色 | eeuss国产一区二区三区黑人 | 日日爱网站| 奇米在线777 | 日韩高清在线一区 | 国产一二三区在线视频 | 天天爽夜夜爽一区二区三区 | 成人在线激情视频 | 丝袜诱惑一区二区 | 欧美人妖乱大交 | 少妇一级淫免费播放 | 欧美综合网站 | 欧美激情一二三 | 91麻豆蜜桃一区二区三区 | a∨鲁丝一区鲁丝二区鲁丝三区 | 最近2019中文字幕大全第二页 | 国产又粗又猛又黄又爽无遮挡 | 午夜爽爽爽 | 黄色片网站国产 | 国产欧美日韩一区二区三区 | 香蕉av777xxx色综合一区 | 免费观看黄色小视频 | 国产成人一区 | 黄色免费在线观看网站 | 法国空姐在线观看完整版 | 美日韩一级 | japanese在线| 精品爆乳一区二区三区 | 成人黄色激情小说 | 日韩影院在线 | 午夜资源网 | 2021狠狠操 | 天干夜天干天天天爽视频 | 国产av天堂无码一区二区三区 | 3p在线播放| 国产中文网 | 老子午夜影院 | 秘密基地免费观看完整版中文 | 国产精品探花一区二区在线观看 | 国产亚洲女人久久久久毛片 | av免费观看网站 | 国产精品成人免费一区久久羞羞 | 91亚洲精品国偷拍 | 免费看黄网站在线 | 欧美一区二区三区影视 | 免费高清视频在线观看 | 成人爱爱视频 | 在线免费观看小视频 | 男女啪啪无遮挡 | 爱情岛黄色 | 男人的天堂欧美 | 国内老熟妇对白xxxxhd | 一区二区在线影院 | 日本熟妇乱子伦xxxx | 69国产| 亚洲自拍偷拍网站 | 黄色小网站在线观看 | 美女毛片视频 | 五十路中文字幕 | av资源在线| 无码aⅴ精品一区二区三区 精品久久在线 | 超碰免费看 | 奴色虐av一区二区三区 | 国产成人黄色片 | 国内成人精品视频 | 37p粉嫩大胆色噜噜噜 | 欧美特黄视频 | 亚洲第一免费网站 |