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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

java 状态设计模式_JAVA设计模式:状态模式

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

轉(zhuǎn)載:http://www.cnblogs.com/pony1223/p/7518226.html

一、引出狀態(tài)模式

假設(shè)我們現(xiàn)在有一個糖果機項目,那么我們知道正常一般糖果機提供給用戶的行為有這么幾種:投入硬幣、轉(zhuǎn)動曲柄、退出硬幣幾種行為;那么糖果機呢一般有這幾中狀態(tài),待機狀態(tài)、持有硬幣的準(zhǔn)備狀態(tài)、運行狀態(tài)即正在售出狀態(tài)和初始狀態(tài) 這么幾種正常狀態(tài)。 我們發(fā)現(xiàn)處于不同狀態(tài)的時候,持有的行為是不一樣的,圖如下:

如果我們采用傳統(tǒng)的方法來寫代碼,那么在投入硬幣這個行為操作的時候,我們會進(jìn)行狀態(tài)的判斷,只有在處于待機狀態(tài)情況下這種行為是正常的,而其他則非正常,那么其他行為也一樣,都需要去先判斷下當(dāng)前的狀態(tài)來進(jìn)行操作。得到的代碼則為:

1 package study.designmode.statemode;

2

3 public class CandyMachine {

4

5 final static int SoldOutState = 0; //初始狀態(tài)

6 final static int OnReadyState = 1; //待機狀態(tài)

7 final static int HasCoin = 2; //準(zhǔn)備狀態(tài)

8 final static int SoldState = 3; //售出狀態(tài)

9

10 private int state = SoldOutState; //變量,用于存放當(dāng)前的狀態(tài)值

11 private int count = 0; //糖果的數(shù)目

12

13 public CandyMachine(int count) {

14 this.count = count;

15 if (count > 0) {

16 state = OnReadyState;

17 }

18 }

19

20 //投入硬幣行為的時候,通過判斷當(dāng)前的狀態(tài)來匹配所有的狀態(tài).

21 public void insertCoin() {

22 switch (state) {

23 case SoldOutState:

24 System.out.println("you can't insert coin,the machine sold out!");

25 break;

26 case OnReadyState: //只有在待機狀態(tài)的時候,投入硬幣行為正確,并將狀態(tài)改變?yōu)闇?zhǔn)備狀態(tài)

27 state = HasCoin;

28 System.out

29 .println("you have inserted a coin,next,please turn crank!");

30 break;

31 case HasCoin:

32 System.out.println("you can't insert another coin!");

33

34 break;

35 case SoldState:

36 System.out.println("please wait!we are giving you a candy!");

37

38 break;

39 }

40

41 }

42

43 //回退硬幣

44 public void returnCoin() {

45 switch (state) {

46 case SoldOutState:

47 System.out

48 .println("you can't return,you haven't inserted a coin yet!");

49 break;

50 case OnReadyState:

51 System.out.println("you haven't inserted a coin yet!");

52 break;

53 case HasCoin:

54

55 System.out.println("coin return!");

56 state = OnReadyState;

57

58 break;

59 case SoldState:

60 System.out.println("sorry,you already have turned the crank!");

61

62 break;

63 }

64

65 }

66

67 //轉(zhuǎn)動曲柄

68 public void turnCrank() {

69 switch (state) {

70 case SoldOutState:

71 System.out.println("you turned,but there are no candies!");

72 break;

73 case OnReadyState:

74 System.out.println("you turned,but you haven't inserted a coin!");

75 break;

76 case HasCoin:

77 System.out.println("crank turn...!");

78 state = SoldState;

79 dispense();

80 break;

81 case SoldState:

82 System.out

83 .println("we are giving you a candy,turning another get nothing,!");

84 break;

85 }

86

87 }

88

89 //觸發(fā)發(fā)放糖果行為

90 private void dispense() {

91 count = count - 1;

92 System.out.println("a candy rolling out!");

93 if (count > 0) {

94 state = OnReadyState;

95 } else {

96 System.out.println("Oo,out of candies");

97 state = SoldOutState;

98 }

99

100 }

101

102 public void printstate() {

103

104 switch (state) {

105 case SoldOutState:

106 System.out.println("***SoldOutState***");

107 break;

108 case OnReadyState:

109 System.out.println("***OnReadyState***");

110 break;

111 case HasCoin:

112

113 System.out.println("***HasCoin***");

114

115 break;

116 case SoldState:

117 System.out.println("***SoldState***");

118 break;

119 }

120

121 }

122 }

那么上面這種方式存在什么問題呢?首先很直觀的感受就是:

1.存在大量的switch case 語句 ?當(dāng)然可以用if ?else 也是一樣的。

2.可擴展性差,并且一旦要加入一種新的狀態(tài),那么就會要修改所有的switch case ?不符合開閉原則

3.沒有采用面向?qū)ο蟮姆绞饺シ庋b

比如,這個時候,新增加了一種狀態(tài),贏家狀態(tài),即可以獲取到兩粒糖果;那么如果用上面的方式,肯定是不符合開閉原則的,同時擴展性也是不好的;那么我們有什么其它的方式來解決呢?

二、解決辦法

為了解決上面的問題,我們首先分析項目中變化的部分和不變的部分,抽化出變化的部分,我們發(fā)現(xiàn)糖果機提供的行為一般是不變的,就是投入硬幣、轉(zhuǎn)動曲柄給、退回硬幣、機器發(fā)放糖果;而糖果機的狀態(tài)是可以變化的,可以新增出一種狀態(tài)來,比如我們說的贏家狀態(tài)。那么我們這個抽出變化的部分,即我們說的狀態(tài),于是出現(xiàn)了下面的結(jié)構(gòu)設(shè)計方案:

這個結(jié)構(gòu)圖告訴我們,提煉出狀態(tài)接口出來,然后將各個狀態(tài)抽出,并去實現(xiàn)接口,每個狀態(tài)都持有投入硬幣,退回硬幣,轉(zhuǎn)動曲柄、售出糖果這幾種行為對應(yīng)的方法做出相應(yīng);而糖果機持有所有的狀態(tài),并通過引用狀態(tài)接口來操作各個狀態(tài);這種設(shè)計架構(gòu)就是我們說的狀態(tài)模式。

狀態(tài)模式定義:對象行為的變化是由于狀態(tài)的變化引入,那么即當(dāng)內(nèi)部狀態(tài)發(fā)生變化的時候,就會改變對象的行為,而這種改變視乎就改變了整個類。

那么現(xiàn)在采用狀態(tài)模式來解決問題:

1.首先定義接口:

package study.designmode.statemode.state;

public interface State {

public void insertCoin();

public void returnCoin();

public void turnCrank();

public void dispense();

public void printstate();

}

2.定義各個狀態(tài)的實現(xiàn)類

準(zhǔn)備狀態(tài):

package study.designmode.statemode.state;

import java.util.Random;

public class HasCoin implements State {

private CandyMachine mCandyMachine;

public HasCoin(CandyMachine mCandyMachine) {

this.mCandyMachine = mCandyMachine;

}

@Override

public void insertCoin() {

// TODO Auto-generated method stub

System.out.println("you can't insert another coin!");

}

@Override

public void returnCoin() {

// TODO Auto-generated method stub

System.out.println("coin return!");

mCandyMachine.setState(mCandyMachine.mOnReadyState);

}

@Override

public void turnCrank() {

// TODO Auto-generated method stub

System.out.println("crank turn...!");

Random ranwinner=new Random();

int winner=ranwinner.nextInt(10);

if(winner==0)

{

mCandyMachine.setState(mCandyMachine.mWinnerState);

}else

{

mCandyMachine.setState(mCandyMachine.mSoldState);

}

}

@Override

public void dispense() {

}

@Override

public void printstate() {

// TODO Auto-generated method stub

System.out.println("***HasCoin***");

}

}

說明:我們會發(fā)現(xiàn)里面存在一個糖果機的屬性,而之所以存在這個屬性,就是因為糖果機中持有所有的狀態(tài),而在準(zhǔn)備狀態(tài)下,肯定會由于某種行為發(fā)生狀態(tài)改變,而要改變的狀態(tài)都在糖果機中,所以持有一個糖果機屬性,下面也一樣,不在重復(fù)說明。

準(zhǔn)備狀態(tài):

package study.designmode.statemode.state;

public class OnReadyState implements State {

private CandyMachine mCandyMachine;

public OnReadyState(CandyMachine mCandyMachine)

{

this.mCandyMachine=mCandyMachine;

}

@Override

public void insertCoin() {

// TODO Auto-generated method stub

System.out

.println("you have inserted a coin,next,please turn crank!");

mCandyMachine.setState(mCandyMachine.mHasCoin);

}

@Override

public void returnCoin() {

// TODO Auto-generated method stub

System.out.println("you haven't inserted a coin yet!");

}

@Override

public void turnCrank() {

// TODO Auto-generated method stub

System.out.println("you turned,but you haven't inserted a coin!");

}

@Override

public void dispense() {

// TODO Auto-generated method stub

}

@Override

public void printstate() {

// TODO Auto-generated method stub

System.out.println("***OnReadyState***");

}

}

初始狀態(tài):

package study.designmode.statemode.state;

public class SoldOutState implements State {

private CandyMachine mCandyMachine;

public SoldOutState(CandyMachine mCandyMachine)

{

this.mCandyMachine=mCandyMachine;

}

@Override

public void insertCoin() {

// TODO Auto-generated method stub

System.out.println("you can't insert coin,the machine sold out!");

}

@Override

public void returnCoin() {

// TODO Auto-generated method stub

System.out

.println("you can't return,you haven't inserted a coin yet!");

}

@Override

public void turnCrank() {

// TODO Auto-generated method stub

System.out.println("you turned,but there are no candies!");

}

@Override

public void dispense() {

// TODO Auto-generated method stub

}

@Override

public void printstate() {

// TODO Auto-generated method stub

System.out.println("***SoldOutState***");

}

}

售出狀態(tài):

package study.designmode.statemode.state;

public class SoldState implements State {

private CandyMachine mCandyMachine;

public SoldState(CandyMachine mCandyMachine)

{

this.mCandyMachine=mCandyMachine;

}

@Override

public void insertCoin() {

// TODO Auto-generated method stub

System.out.println("please wait!we are giving you a candy!");

}

@Override

public void returnCoin() {

// TODO Auto-generated method stub

System.out.println("you haven't inserted a coin yet!");

}

@Override

public void turnCrank() {

// TODO Auto-generated method stub

System.out

.println("we are giving you a candy,turning another get nothing,!");

}

@Override

public void dispense() {

// TODO Auto-generated method stub

mCandyMachine.releaseCandy();

if (mCandyMachine.getCount() > 0) {

mCandyMachine.setState(mCandyMachine.mOnReadyState);

} else {

System.out.println("Oo,out of candies");

mCandyMachine.setState(mCandyMachine.mSoldOutState);

}

}

@Override

public void printstate() {

// TODO Auto-generated method stub

System.out.println("***SoldState***");

}

}

贏家狀態(tài):

package study.designmode.statemode.state;

public class WinnerState implements State {

private CandyMachine mCandyMachine;

public WinnerState(CandyMachine mCandyMachine) {

this.mCandyMachine = mCandyMachine;

}

@Override

public void insertCoin() {

// TODO Auto-generated method stub

System.out.println("please wait!we are giving you a candy!");

}

@Override

public void returnCoin() {

// TODO Auto-generated method stub

System.out.println("you haven't inserted a coin yet!");

}

@Override

public void turnCrank() {

// TODO Auto-generated method stub

System.out

.println("we are giving you a candy,turning another get nothing,!");

}

@Override

public void dispense() {

// TODO Auto-generated method stub

mCandyMachine.releaseCandy();

if (mCandyMachine.getCount() == 0) {

mCandyMachine.setState(mCandyMachine.mSoldOutState);

} else {

System.out.println("you are a winner!you get another candy!");

mCandyMachine.releaseCandy();

if (mCandyMachine.getCount() > 0) {

mCandyMachine.setState(mCandyMachine.mOnReadyState);

} else {

System.out.println("Oo,out of candies");

mCandyMachine.setState(mCandyMachine.mSoldOutState);

}

}

}

@Override

public void printstate() {

// TODO Auto-generated method stub

System.out.println("***WinnerState***");

}

}

3.糖果機,糖果機要持有所有的狀態(tài),并在初始化的時候,要設(shè)置其開始的狀態(tài),然后糖果的各個行為,就委托到了各個狀態(tài)中自己維護(hù),代碼如下:

package study.designmode.statemode.state;

public class CandyMachine {

State mSoldOutState;

State mOnReadyState;

State mHasCoin;

State mSoldState;

State mWinnerState;

private State state;

private int count = 0;

public CandyMachine(int count) {

this.count = count;

mSoldOutState = new SoldOutState(this);

mOnReadyState = new OnReadyState(this);

mHasCoin = new HasCoin(this);

mSoldState = new SoldState(this);

mWinnerState = new WinnerState(this);

if (count > 0) {

state = mOnReadyState;

} else {

state = mSoldOutState;

}

}

public void setState(State state) {

this.state = state;

}

public void insertCoin() {

state.insertCoin();

}

public void returnCoin() {

state.returnCoin();

}

public void turnCrank() {

state.turnCrank();

state.dispense();

}

void releaseCandy() {

// TODO Auto-generated method stub

if (count > 0) {

count = count - 1;

System.out.println("a candy rolling out!");

}

}

public int getCount() {

return count;

}

public void printstate() {

state.printstate();

}

}

4.測試類

package study.designmode.statemode.state;

public class MainTest {

public static void main(String[] args) {

CandyMachine mCandyMachine = new CandyMachine(6);

mCandyMachine.printstate();

mCandyMachine.insertCoin();

mCandyMachine.printstate();

mCandyMachine.turnCrank();

mCandyMachine.printstate();

mCandyMachine.insertCoin();

mCandyMachine.printstate();

mCandyMachine.turnCrank();

mCandyMachine.printstate();

}

}

結(jié)果如下:

可以和開始的傳統(tǒng)方案對比,結(jié)果是一樣的,但是具備了可擴展性。

三、總結(jié)

通過上面的例子,我們已經(jīng)對狀態(tài)模式有所了解,下面我們做一個總結(jié),來回顧我們的狀態(tài)模式:

1.狀態(tài)模式允許對象在內(nèi)部狀態(tài)改變時改變它的行為,對象看起來好像修改了它的類。? ?理解:這個模式將狀態(tài)封裝成獨立的類,并將動作委托到代表當(dāng)前狀態(tài)的對象,這就是說行為會隨著內(nèi)部狀態(tài)而改變。? ?“看起來好像修改了它的類”是什么意思呢?從客戶的視角來看:如果說你使用的對象能夠完全改變它的行為,那么你會覺得,這個對象實際上是從別的類實例化而來的。然而,實際上,你知道我們是在使用組合通過簡單引用不同的狀態(tài)對象來造成類改變的假象

2.狀態(tài)模式要點

(1)客戶不會和狀態(tài)進(jìn)行交互,全盤了解狀態(tài)是 context的工作(2)在狀態(tài)模式中,每個狀態(tài)通過持有Context的引用,來實現(xiàn)狀態(tài)轉(zhuǎn)移(3)使用狀態(tài)模式總是會增加設(shè)計中類的數(shù)目,這是為了要獲得程序可擴展性,彈性的代價,如果你的代碼不是一次性的,后期可能會不斷加入不同的狀態(tài),那么狀態(tài)模式的設(shè)計是絕對值得的。【同時也是一個缺點】(4)狀態(tài)類可以被多個context實例共享

3.狀態(tài)模式和策略模式對比

首先讓我們來看看它們之間更多的相似之處:添加新的狀態(tài)或策略都很容易,而且不需要修改使用它們的Context對象。它們都讓你的代碼符合OCP原則(軟件對擴展應(yīng)該是開發(fā)的,對修改應(yīng)該是關(guān)閉的)。在狀態(tài)模式和策略模式中,Context對象對修改是關(guān)閉的,添加新的狀態(tài)或策略,都不需要修改Context。正如狀態(tài)模式中的Context會有初始狀態(tài)一樣,策略模式同樣有默認(rèn)策略。狀態(tài)模式以不同的狀態(tài)封裝不同的行為,而策略模式以不同的策略封裝不同的行為。它們都依賴子類去實現(xiàn)相關(guān)行為

兩個模式的差別在于它們的”意圖“不同:

狀態(tài)模式幫助對象管理狀態(tài),我們將一群行為封裝早狀態(tài)對象中,context的行為隨時可委托到那些狀態(tài)中的一個.隨著時間的流逝,當(dāng)前狀態(tài)在狀態(tài)對象集合中游走改變,以反映context內(nèi)部狀態(tài),因此,context的行為也會跟著改變。當(dāng)要添加新的狀態(tài)時,不需要修改原來代碼添加新的狀態(tài)類即可。 而策略模式允許Client選擇不同的行為。通過封裝一組相關(guān)算法,為Client提供運行時的靈活性。Client可以在運行時,選擇任一算法,而不改變使用算法的Context。一些流行的策略模式的例子是寫那些使用算法的代碼,例如加密算法、壓縮算法、排序算法。客戶通常主動指定context所要組合的策略對象是哪一個.

一句話:最根本的差異在于策略模式是在求解同一個問題的多種解法,這些不同解法之間毫無關(guān)聯(lián);狀態(tài)模式則不同,狀態(tài)模式要求各個狀態(tài)之間有所關(guān)聯(lián),以便實現(xiàn)狀態(tài)轉(zhuǎn)移。

總結(jié)

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

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