設(shè)計(jì)模式之狀態(tài)模式

在開發(fā)過程中,我們經(jīng)常會(huì)遇到很多if-else的判斷恒削,有的會(huì)有很多層吠架,當(dāng)然也不是說所有的涉及到if-else判斷的都要用該模式凡涩,但是提供了一個(gè)思路讓我們把代碼寫的更加的可擴(kuò)展,可維護(hù)豌鸡,按照對(duì)擴(kuò)展開發(fā)嘿般,對(duì)修改關(guān)閉的設(shè)計(jì)原則段标,可以很好的方便以后代碼的維護(hù)。

狀態(tài)模式封裝基于狀態(tài)的行為博个,并且將該行為委托到當(dāng)前狀態(tài)怀樟。

首先我們看一個(gè)案例:

以我們在商場或者小店旁邊經(jīng)常看到的糖果機(jī)器為例盆佣,當(dāng)投入一塊錢往堡,轉(zhuǎn)動(dòng)手柄,糖果機(jī)售出糖果共耍,如果糖果機(jī)器里有糖果虑灰,則發(fā)放糖果,糖果數(shù)據(jù)減少一顆痹兜,如果沒有一塊錢要求投入一塊錢穆咐,如果旋轉(zhuǎn)退回一塊錢,則退回一塊錢字旭;

這里邊涉及到了幾個(gè)狀態(tài):

1:有一塊錢

2:沒有一塊錢

3:售出糖果

4:糖果賣完了

運(yùn)用狀態(tài)模式我們該如何解決該問題呢对湃?

讓我們先來看一下狀態(tài)模式的定義:允許對(duì)象在內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來好像修改了它的類遗淳。

概念看起來總是抽象的拍柒,對(duì)象怎么在內(nèi)部狀態(tài)改變時(shí)改變它的行為,這就需要我們?nèi)ソ鉀Q實(shí)現(xiàn)屈暗。

廢話不多說拆讯,我們來看一下狀態(tài)模式的模型:

Context上下文類:可以擁有一些內(nèi)部狀態(tài)

State:定義一個(gè)所有具體狀態(tài)的共同接口,任何狀態(tài)都實(shí)現(xiàn)這個(gè)相同接口

ConcreteSateA:具體狀態(tài)养叛,處理來自context的請求种呐,每一個(gè)具體狀態(tài)都提供了它自己對(duì)于請求的實(shí)現(xiàn),所以當(dāng)context改變狀態(tài)時(shí)候行為也跟著改變弃甥。

接著我們來實(shí)現(xiàn):此處的GumballMachineReuniform就是Context

public classGumballMachineReuniform {

StatesoldOutState;

StatenoQuarterState;

StatehasQuarterState;

StatesoldState;

StatewinnerState;

StatecurrentState=soldOutState;

//this variable shows how many candy in this machine

intcount=0;

publicGumballMachineReuniform(intnumberOfGumball){

soldOutState=newSoldOutState(this);

noQuarterState=newNoQuarterState(this);

hasQuarterState=newHasQuarterState(this);

soldState=newSoldState(this);

winnerState=newWinnerState(this);

this.count= numberOfGumball;

if(count>0) {

currentState=noQuarterState;

}

}

public voidinsertQuarter() {

currentState.insertQuarter();

}

public voidejectQuarter() {

currentState.ejectQuarter();

}

public voidturnCrank() {

currentState.turnCrank();

currentState.dispense();

}

public voidsetState(State state) {

this.currentState= state;

}

//reinforce to release ball

public voidreleaseBall() {

System.out.println("A gumball comes rolling out the slot .... ");

if(count!=0) {

count=count-1;

}

}

publicState getSoldOutState() {

returnsoldOutState;

}

public voidsetSoldOutState(State soldOutState) {

this.soldOutState= soldOutState;

}

publicState getNoQuarterState() {

returnnoQuarterState;

}

public voidsetNoQuarterState(State noQuarterState) {

this.noQuarterState= noQuarterState;

}

publicState getHasQuarterState() {

returnhasQuarterState;

}

public voidsetHasQuarterState(State hasQuarterState) {

this.hasQuarterState= hasQuarterState;

}

publicState getSoldState() {

returnsoldState;

}

public voidsetSoldState(State soldState) {

this.soldState= soldState;

}

public intgetCount() {

returncount;

}

public voidsetCount(intcount) {

this.count= count;

}

publicState getWinnerState() {

returnwinnerState;

}

public voidsetWinnerState(State winnerState) {

this.winnerState= winnerState;

}

@Override

publicString toString() {

returncount+" gumball ";

}

publicState getState() {

returncurrentState;

}

}

//狀態(tài)接口

public interfaceState {

public voidinsertQuarter();

public voidejectQuarter();

public voidturnCrank();

public voiddispense();

//具體狀態(tài)類

public classSoldStateimplementsState {

GumballMachineReuniformgumballMachineReuniform;

publicSoldState(GumballMachineReuniform gumballMachineReuniform){

this.gumballMachineReuniform= gumballMachineReuniform;

}

@Override

public voidinsertQuarter() {

System.out.println("You can't insert another coin ,please wait machine give u a gumball");

}

@Override

public voidejectQuarter() {

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

}

@Override

public voidturnCrank() {

System.out.println("You can't turn crank twice ");

}

@Override

public voiddispense() {

gumballMachineReuniform.releaseBall();

if(gumballMachineReuniform.getCount() >0) {

gumballMachineReuniform.setState(gumballMachineReuniform.getNoQuarterState());

}else{

System.out.println("Oops out of gumball !");

gumballMachineReuniform.setState(gumballMachineReuniform.getSoldOutState());

}

}

@Override

publicString toString() {

return" solding state ";

}

}

public classSoldOutStateimplementsState {

GumballMachineReuniformgumballMachine;

publicSoldOutState(GumballMachineReuniform gumballMachineReuniform) {

this.gumballMachine= gumballMachineReuniform;

}

@Override

public voidinsertQuarter() {

System.out.println("gumball has been sold out ");

}

@Override

public voidejectQuarter() {

System.out.println("can not eject quarter ");

}

@Override

public voidturnCrank() {

System.out.println("can not turn crank sold out gumball ");

}

@Override

public voiddispense() {

System.out.println("can not dispense crank sold out ");

}

@Override

publicString toString() {

return" already sold out ";

}

}

public classNoQuarterStateimplementsState {

GumballMachineReuniformgumballMachine;

publicNoQuarterState(GumballMachineReuniform gumballMachine){

this.gumballMachine= gumballMachine;

}

@Override

public voidinsertQuarter() {

System.out.println("you have insert one coin !!");

gumballMachine.setState(gumballMachine.getHasQuarterState());

}

@Override

public voidejectQuarter() {

System.out.println("you haven't insert one coin please insert coin first!");

}

@Override

public voidturnCrank() {

System.out.println("you have turned but there's no quarter insert !");

}

@Override

public voiddispense() {

System.out.println("You need to pay first ");

}

@Override

publicString toString() {

return"waiting to insert coin ";

}

}

public classHasQuarterStateimplementsState {

RandomrandomWinner=newRandom(System.currentTimeMillis());

GumballMachineReuniformgumballMachine;

publicHasQuarterState(GumballMachineReuniform gumballMachine) {

this.gumballMachine= gumballMachine;

}

@Override

public voidinsertQuarter() {

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

}

@Override

public voidejectQuarter() {

System.out.println("Quarter returned !");

gumballMachine.setState(gumballMachine.getNoQuarterState());

}

@Override

public voidturnCrank() {

System.out.println("You turned...");

intwinner =randomWinner.nextInt(10);

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

gumballMachine.setState(gumballMachine.getWinnerState());

}else{

gumballMachine.setState(gumballMachine.getSoldState());

}

}

@Override

public voiddispense() {

System.out.println("No gumball dispense ");

}

@Override

publicString toString() {

return"has quarter ";

}

}

以上就是具體的狀態(tài)模式的實(shí)現(xiàn)爽室,也許會(huì)有人說很麻煩,覺得本來可以用if-else或者switch一段代碼解決的問題潘飘,卻增加了這么多的類肮之;狀態(tài)模式確實(shí)會(huì)增加很多類,有幾個(gè)狀態(tài)就會(huì)有幾個(gè)具體的狀態(tài)類卜录,之所以這樣做是為了后期的擴(kuò)展以及維護(hù)戈擒,假如在A類中寫了一堆if-else如果多一個(gè)狀態(tài)就要多追加一個(gè)if-else判斷,也許有人覺得多加一個(gè)if-else判斷也沒什么艰毒,但是如果這里邊有不同的操作或者說在某個(gè)狀態(tài)時(shí)候做一些特殊的操作筐高,if-else判斷就會(huì)很麻煩,且違反了我們的類對(duì)修改關(guān)閉,對(duì)擴(kuò)展開放的涉及原則柑土。

狀態(tài)模式和策略模式比較像蜀肘,但他們的目的不同,策略模式通常會(huì)用行為或者算法來配置context類稽屏,狀態(tài)模式允許Context隨著狀態(tài)的改變而改變行為扮宠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狐榔,隨后出現(xiàn)的幾起案子坛增,更是在濱河造成了極大的恐慌,老刑警劉巖薄腻,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收捣,死亡現(xiàn)場離奇詭異,居然都是意外死亡庵楷,警方通過查閱死者的電腦和手機(jī)罢艾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尽纽,“玉大人咐蚯,你說我怎么就攤上這事∨撸” “怎么了仓蛆?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挎春。 經(jīng)常有香客問我,道長豆拨,這世上最難降的妖魔是什么直奋? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮施禾,結(jié)果婚禮上脚线,老公的妹妹穿的比我還像新娘。我一直安慰自己弥搞,他們只是感情好邮绿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攀例,像睡著了一般船逮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粤铭,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天挖胃,我揣著相機(jī)與錄音,去河邊找鬼。 笑死酱鸭,一個(gè)胖子當(dāng)著我的面吹牛吗垮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凹髓,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烁登,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蔚舀?” 一聲冷哼從身側(cè)響起饵沧,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝗敢,沒想到半個(gè)月后捷泞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寿谴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锁右,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讶泰。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咏瑟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痪署,到底是詐尸還是另有隱情码泞,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布狼犯,位于F島的核電站余寥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏悯森。R本人自食惡果不足惜宋舷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓢姻。 院中可真熱鬧祝蝠,春花似錦、人聲如沸幻碱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽褥傍。三九已至儡嘶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恍风,已是汗流浹背社付。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工承疲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸥咖。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓燕鸽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親啼辣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啊研,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法鸥拧,內(nèi)部類的語法党远,繼承相關(guān)的語法,異常的語法富弦,線程的語...
    子非魚_t_閱讀 31,631評(píng)論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理沟娱,服務(wù)發(fā)現(xiàn),斷路器腕柜,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • 一济似、設(shè)計(jì)模式的分類 總體來說設(shè)計(jì)模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式盏缤、抽象工廠模式砰蠢、單例模式、建造者...
    RamboLI閱讀 749評(píng)論 0 1
  • 面向?qū)ο蟮牧笤瓌t 單一職責(zé)原則 所謂職責(zé)是指類變化的原因唉铜。如果一個(gè)類有多于一個(gè)的動(dòng)機(jī)被改變台舱,那么這個(gè)類就具有多于...
    JxMY閱讀 940評(píng)論 1 3
  • 晚上8點(diǎn),手機(jī)來電--同學(xué)老寧熬甫,接起來電話里劈頭蓋臉一通炮火。 “作為一個(gè)老師蔓罚,怎么能這么說話椿肩?我還沒見過素質(zhì)這么...
    輕輕地風(fēng)閱讀 1,232評(píng)論 1 5