Java設(shè)計模式之狀態(tài)模式StatePattern詳解_第1頁
Java設(shè)計模式之狀態(tài)模式StatePattern詳解_第2頁
Java設(shè)計模式之狀態(tài)模式StatePattern詳解_第3頁
Java設(shè)計模式之狀態(tài)模式StatePattern詳解_第4頁
Java設(shè)計模式之狀態(tài)模式StatePattern詳解_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第Java設(shè)計模式之狀態(tài)模式StatePattern詳解目錄概述UML類圖狀態(tài)模式與策略模式誰決定狀態(tài)轉(zhuǎn)換的流向State是接口還是抽象類應(yīng)用案例分析狀態(tài)抽象類可以抽獎的狀態(tài)獎品發(fā)放完畢狀態(tài)發(fā)放獎品的狀態(tài)不能抽獎狀態(tài)抽獎活動(Context)測試狀態(tài)模式

概述

狀態(tài)模式允許對象在內(nèi)部狀態(tài)改變時改變它的行為,對象看起來好像修改了它的類。這個模式將狀態(tài)封裝成獨(dú)立的類,并將動作委托到代表當(dāng)前狀態(tài)的對象,我們知道行為會隨著內(nèi)部狀態(tài)而改變。

一個對象看起來好像修改了它的類是什么意思呢?從客戶的視角來看:如果說你使用的對象能夠完全改變它的行為,那么你會覺得,這個對象實(shí)際上是從別的類實(shí)例化而來的。然而,實(shí)際上,你知道我們是在使用組合通過簡單引用不同的狀態(tài)對象來造成類改變的假象。

狀態(tài)模式它主要用來解決對象在多種狀態(tài)轉(zhuǎn)換時,需要對外輸出不同的行為的問題。狀態(tài)和行為是一一對應(yīng)的,狀態(tài)之間可以相互轉(zhuǎn)換。

UML類圖

Context是一個類,它可以擁有一些內(nèi)部狀態(tài)。State接口定義了一個所有具體狀態(tài)的共同接口,任何狀態(tài)都實(shí)現(xiàn)這個相同的接口,這樣一來狀態(tài)之間可以互相替換。不管在什么時候,只要有人調(diào)用Context的request()方法,它就會被委托到狀態(tài)來處理。ConcreteState處理來自Context的請求。每一個ConcreteState都提供了它自己對于請求的實(shí)現(xiàn)。所以,當(dāng)Context改變狀態(tài)時,行為也跟著改變。

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

以狀態(tài)模式而言,我們將一群行為封裝在狀態(tài)對象中,context的行為隨時可委托到那些狀態(tài)對象中的一個。隨著時間的流逝,當(dāng)前狀態(tài)在狀態(tài)對象集合中游走改變,以反映出context內(nèi)部的狀態(tài),因此context的行為也會隨著改變。但是context的客戶對于狀態(tài)對象了解不多,甚至根本是渾然不覺。

而以策略模式而言,客戶通常主動指定Context所要組合的策略對象是哪一個?,F(xiàn)在,固然策略模式讓我們具有彈性,能夠在運(yùn)行時改變策略,但對于某個context對象來說,通常都只有一個最適當(dāng)?shù)牟呗詫ο蟆?/p>

一般來說,我們把策略模式想成是除了繼承之外的一種彈性替代方案。如果你使用繼承定義了一個類的行為,你將被這個行為困住,甚至要修改它都很難。有了策略模式,你可以通過組合不同的對象來改變行為。

我們把狀態(tài)模式想成是不用在context中放置許多條件判斷的替代方案。通過將行為包裝進(jìn)狀態(tài)對象中,你可以通過在context內(nèi)見到地改變狀態(tài)對象來改變context的行為。

誰決定狀態(tài)轉(zhuǎn)換的流向

Context或者ConcreteState都可以。

一般來講,當(dāng)狀態(tài)轉(zhuǎn)換是固定的時候,就適合放在Context中。然而,當(dāng)轉(zhuǎn)換是動態(tài)的時候,通常就會放在狀態(tài)類中。

將狀態(tài)放在狀態(tài)類中的缺點(diǎn)是:狀態(tài)類之間產(chǎn)生了依賴。

State是接口還是抽象類

答:都可以。如果我們沒有共同的功能可以放進(jìn)抽象類中,就會使用接口。在你實(shí)現(xiàn)狀態(tài)模式時,很可能想使用抽象類。這么一來,當(dāng)你以后需要在抽象類中加入新的方法是就很容易,不需要打破具體狀態(tài)的實(shí)現(xiàn)。

應(yīng)用案例分析

請編寫程序完成APP抽獎活動具體要求如下:

假如每參加一次這個活動要扣除用戶50積分,中獎概率是10%獎品數(shù)量固定,抽完就不能抽獎活動有四個狀態(tài):可以抽獎、不能抽獎、發(fā)放獎品和獎品領(lǐng)完活動的四個狀態(tài)轉(zhuǎn)換關(guān)系圖

那么需要如何做呢?

定義出一個接口(或抽象類)叫狀態(tài)接口,每個狀態(tài)都實(shí)現(xiàn)(繼承)它。接口有扣除積分方法、抽獎方法、發(fā)放獎品方法

狀態(tài)抽象類

/**

*狀態(tài)抽象類

publicabstractclassState{

//扣除積分-50

publicabstractvoiddeductMoney();

//是否抽中獎品

publicabstractbooleanraffle();

//發(fā)放獎品

publicabstractvoiddispensePrize();

}

可以抽獎的狀態(tài)

publicclassCanRaffleStateextendsState{

RaffleActivityactivity;

publicCanRaffleState(RaffleActivityactivity){

this.activity=activity;

//已經(jīng)扣除了積分,不能再扣

@Override

publicvoiddeductMoney(){

System.out.println("已經(jīng)扣取過了積分");

//可以抽獎,抽完獎后,根據(jù)實(shí)際情況,改成新的狀態(tài)

@Override

publicbooleanraffle(){

System.out.println("正在抽獎,請稍等!");

Randomr=newRandom();

intnum=r.nextInt(10);

//10%中獎機(jī)會

if(num==0){

//改變活動狀態(tài)為發(fā)放獎品context

activity.setState(activity.getDispenseState());

returntrue;

}else{

System.out.println("很遺憾沒有抽中獎品!");

//改變狀態(tài)為不能抽獎

activity.setState(activity.getNoRafflleState());

returnfalse;

//不能發(fā)放獎品

@Override

publicvoiddispensePrize(){

System.out.println("沒中獎,不能發(fā)放獎品");

}

獎品發(fā)放完畢狀態(tài)

/**

*獎品發(fā)放完畢狀態(tài)

*說明,當(dāng)我們activity改變成DispenseOutState,抽獎活動結(jié)束

publicclassDispenseOutStateextendsState{

//初始化時傳入活動引用

RaffleActivityactivity;

publicDispenseOutState(RaffleActivityactivity){

this.activity=activity;

@Override

publicvoiddeductMoney(){

System.out.println("獎品發(fā)送完了,請下次再參加");

@Override

publicbooleanraffle(){

System.out.println("獎品發(fā)送完了,請下次再參加");

returnfalse;

@Override

publicvoiddispensePrize(){

System.out.println("獎品發(fā)送完了,請下次再參加");

}

發(fā)放獎品的狀態(tài)

publicclassDispenseStateextendsState{

//初始化時傳入活動引用,發(fā)放獎品后改變其狀態(tài)

RaffleActivityactivity;

publicDispenseState(RaffleActivityactivity){

this.activity=activity;

@Override

publicvoiddeductMoney(){

System.out.println("不能扣除積分");

@Override

publicbooleanraffle(){

System.out.println("不能抽獎");

returnfalse;

//發(fā)放獎品

@Override

publicvoiddispensePrize(){

if(activity.getCount()0){

System.out.println("恭喜中獎了");

//改變狀態(tài)為不能抽獎

activity.setState(activity.getNoRafflleState());

}else{

System.out.println("很遺憾,獎品發(fā)送完了");

//改變狀態(tài)為獎品發(fā)送完畢,后面我們就不可以抽獎

activity.setState(activity.getDispensOutState());

//System.out.println("抽獎活動結(jié)束");

//System.exit(0);

}

不能抽獎狀態(tài)

publicclassNoRaffleStateextendsState{

//初始化時傳入活動引用,扣除積分后改變其狀態(tài)

RaffleActivityactivity;

publicNoRaffleState(RaffleActivityactivity){

this.activity=activity;

//當(dāng)前狀態(tài)可以扣積分,扣除后,將狀態(tài)設(shè)置成可以抽獎狀態(tài)

@Override

publicvoiddeductMoney(){

System.out.println("扣除50積分成功,您可以抽獎了");

activity.setState(activity.getCanRaffleState());

//當(dāng)前狀態(tài)不能抽獎

@Override

publicbooleanraffle(){

System.out.println("扣了積分才能抽獎喔!");

returnfalse;

//當(dāng)前狀態(tài)不能發(fā)獎品

@Override

publicvoiddispensePrize(){

System.out.println("不能發(fā)放獎品");

}

抽獎活動(Context)

publicclassRaffleActivity{

//state表示活動當(dāng)前的狀態(tài),是變化

Statestate=null;

//獎品數(shù)量

intcount=0;

//四個屬性,表示四種狀態(tài)

StatenoRafflleState=newNoRaffleState(this);

StatecanRaffleState=newCanRaffleState(this);

StatedispenseState=newDispenseState(this);

StatedispensOutState=newDispenseOutState(this);

//構(gòu)造器

//1.初始化當(dāng)前的狀態(tài)為noRafflleState(即不能抽獎的狀態(tài))

//2.初始化獎品的數(shù)量

publicRaffleActivity(intcount){

this.state=getNoRafflleState();

this.count=count;

//扣分,調(diào)用當(dāng)前狀態(tài)的deductMoney

publicvoiddebuctMoney(){

state.deductMoney();

//抽獎

publicvoidraffle(){

//如果當(dāng)前的狀態(tài)是抽獎成功

if(state.raffle()){

//領(lǐng)取獎品

state.dispensePrize();

publicStategetState(){

returnstate;

publicvoidsetState(Statestate){

this.state=state;

//這里請大家注意,每領(lǐng)取一次獎品,count--

publicintgetCount(){

intcurCount=count;

count--;

returncurCount;

publicvoidsetCount(intcount){

this.count=count;

publicStategetNoRafflleState(){

returnnoRafflleState;

publicvoidsetNoRafflleState(StatenoRafflleState){

this.noRafflleState=noRafflleState;

publicStategetCanRaffleState(){

returncanRaffleState;

publicvoidsetCanRaffleState(StatecanRaffleState){

this.canRaffleState=canRaffleState;

publicStategetDispenseState(){

returndispenseState;

publicvoidsetD

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論