Java設計模式百例 - 狀態(tài)模式

本文源碼見:https://github.com/get-set/get-designpatterns/tree/master/state

在狀態(tài)模式(State Pattern)中,類的行為是基于它的狀態(tài)改變的弟蚀。這種類型的設計模式屬于行為型模式。

我們程序猿在碼代碼的時候由于不同的工作狀態(tài),可能寫出質量不一的代碼,并我們不是AI嘛筷笨。

  • 早上上班的時候,休息了一夜,精力旺盛啊片,程序猿能夠高效碼代碼,bug也不多玖像;
  • 當熬夜加班的時候,運轉了一天的大腦無比疲憊齐饮,寫出的代碼常有bug出沒捐寥;
  • 當然,我們也都非常期待在碼代碼的時候能夠達到“天人合一”之境界(雖然這種狀態(tài)通常出現(xiàn)在玩游戲時)祖驱,沒有煩人的會議握恳、沒有別人的打擾,雖然沒有程序猿鼓勵妹子在側捺僻,卻能幾分鐘寫出通常需要幾個小時才能寫出的邏輯乡洼,解決近幾天都未解決的問題崇裁,可謂“碼神附體”!

例子

如果上述情況用代碼來表述的話束昵,我們來設計一下拔稳。

程序猿還是同一個人,但是同一個任務在不同的狀態(tài)下锹雏,可能會達到不同的效果巴比。

注意上邊這句話,有兩個“同一個”和兩個”不同的“礁遵。

人和任務是相同的轻绞,是不變的部分;狀態(tài)和效果是不同的佣耐,是變的部分政勃。按照設計模式的套路,不變的和變化的是要分開來的兼砖,從而滿足”開閉“原則奸远,有利于擴展。

不變的是人(類Developer)和任務(方法Developer.develop())掖鱼,變化的狀態(tài)(類XxxState)作為Developer的成員變量能夠隨時切換看來就可以解決這個問題然走。

由于狀態(tài)是變化的,因此需要不同的類XxxState來描述戏挡,其方法XxxState.develop()正好可以靈活實現(xiàn)不同狀態(tài)下的工作效果芍瑞。

完美!最后還有一個褐墅,按照設計模式的通常套路拆檬,同一類變化的類要抽象為接口或抽象類,并提供統(tǒng)一的接口方法妥凳,從而做到”面向接口“編程竟贯,以應對變化。

設計完畢逝钥,那就開工:

Developer.java

public class Developer {
    private State state;

    public Developer(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void develop() {
        state.coding();
    }
}

Developer維護有State的引用屑那,并提供setState(State)方法切換狀態(tài)。

State.java

public interface State {
    void coding();
}

EffectiveState.java

public class EffectiveState implements State {
    public void coding() {
        System.out.println("高效碼代碼艘款,偶有bug持际,人非圣賢嘛~");
    }
}

ExhaustedState.java

public class ExhaustedState implements State {
    public void coding() {
        System.out.println("加班熬夜碼代碼,專業(yè)寫bug");
    }
}

TianRenHeYiState.java

public class TianRenHeYiState implements State {
    public void coding() {
        System.out.println("寫代碼進入天人合一境界哗咆,仿佛三頭六臂蜘欲,碼神附體");
    }
}
狀態(tài)類的抽象

不同的狀態(tài)有不同的實現(xiàn)效果,通過State抽象出統(tǒng)一的接口晌柬。

測試一下:

Client.java

public class Client {
    public static void main(String[] args) {
        Developer developer = new Developer(new EffectiveState());
        developer.develop();
        developer.setState(new ExhaustedState());
        developer.develop();
        developer.setState(new TianRenHeYiState());
        developer.develop();
    }
}

使用DevelopersetState方法切換不同的狀態(tài)姥份,從而實現(xiàn)不同的操作:

高效碼代碼郭脂,偶有bug,人非圣賢嘛~
加班熬夜碼代碼澈歉,專業(yè)寫bug
寫代碼進入天人合一境界展鸡,仿佛三頭六臂,碼神附體

總結

這就是狀態(tài)模式闷祥,將不同的狀態(tài)包裝為不同的類娱颊,供其本體引用,從而實現(xiàn)靈活的狀態(tài)切換凯砍。

看到這里其實感覺狀態(tài)模式和策略模式很像箱硕,狀態(tài)模式是將不同的狀態(tài)對象作為成員變量給使用者(也稱”環(huán)境“),策略模式是將不同的策略對象作為成員變量給使用者(也稱”環(huán)境“)悟衩。其實二者還是有些使用上的區(qū)別的:

  • 策略模式中剧罩,作為成員變量的策略對象通常不會經(jīng)常變化;而狀態(tài)模式在使用者(也稱”環(huán)境“)的整個生命周期中會不斷變化座泳。
  • 策略模式中惠昔,通常并不明確告訴客戶端所選擇的具體策略;而狀態(tài)模式中挑势,所處的狀態(tài)是明確告知客戶端的镇防;
  • 通常策略模式的使用者自己選擇一個具體策略;而狀態(tài)模式的使用者(也稱”環(huán)境“)通常是被動使用某種狀態(tài)潮饱。

使用場景

  • 一個對象的行為依賴于它所處的狀態(tài)来氧,對象的行為必須隨著其狀態(tài)的改變而改變;
  • 對象在某個方法里依賴一重或多重的條件轉移語句香拉,而且其中有大量代碼的時候啦扬。

注意事項

  • 狀態(tài)模式并未規(guī)定哪個角色來進行狀態(tài)切換,上邊的例子是由使用者(也稱”環(huán)境“)的setState方法來切換狀態(tài)凫碌,而有些情況下是由”狀態(tài)“對象本身來切換到下一個狀態(tài)扑毡。
  • 使用者(也稱”環(huán)境“)也可以把自己作為參數(shù)傳遞給狀態(tài)對象,從而狀態(tài)對象也可以調用使用者的方法盛险。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末瞄摊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子苦掘,更是在濱河造成了極大的恐慌泉褐,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸟蜡,死亡現(xiàn)場離奇詭異,居然都是意外死亡挺邀,警方通過查閱死者的電腦和手機揉忘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門跳座,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泣矛,你說我怎么就攤上這事疲眷。” “怎么了您朽?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵狂丝,是天一觀的道長。 經(jīng)常有香客問我哗总,道長几颜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任讯屈,我火速辦了婚禮蛋哭,結果婚禮上,老公的妹妹穿的比我還像新娘涮母。我一直安慰自己谆趾,他們只是感情好,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布叛本。 她就那樣靜靜地躺著沪蓬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪来候。 梳的紋絲不亂的頭發(fā)上跷叉,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機與錄音吠勘,去河邊找鬼性芬。 笑死,一個胖子當著我的面吹牛剧防,可吹牛的內容都是我干的植锉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼峭拘,長吁一口氣:“原來是場噩夢啊……” “哼俊庇!你這毒婦竟也來了?” 一聲冷哼從身側響起鸡挠,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤辉饱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拣展,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彭沼,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年备埃,在試婚紗的時候發(fā)現(xiàn)自己被綠了姓惑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褐奴。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖于毙,靈堂內的尸體忽然破棺而出敦冬,到底是詐尸還是另有隱情,我是刑警寧澤唯沮,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布脖旱,位于F島的核電站,受9級特大地震影響介蛉,放射性物質發(fā)生泄漏萌庆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一甘耿、第九天 我趴在偏房一處隱蔽的房頂上張望踊兜。 院中可真熱鬧,春花似錦佳恬、人聲如沸捏境。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垫言。三九已至,卻和暖如春倾剿,著一層夾襖步出監(jiān)牢的瞬間筷频,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工前痘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凛捏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓芹缔,卻偏偏與公主長得像坯癣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子最欠,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,088評論 25 707
  • 1. Java基礎部分 基礎部分的順序:基本語法示罗,類相關的語法,內部類的語法芝硬,繼承相關的語法蚜点,異常的語法,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 原文鏈接:http://blog.csdn.net/zhangerqing http://www.cnblogs....
    孤獨雜貨鋪閱讀 1,516評論 0 3
  • 小魚和小姐妹包子得了幾張免費拍婚紗照的券,一聽免費便心動了,小魚叫上老公脯倒,包子本也想叫老公一起去实辑,但包子老公是個十...
    小含歌閱讀 461評論 3 2
  • 當激情散去,我們依然前行藻丢,成功之路才剛剛顯現(xiàn)…… 路上一定會經(jīng)歷挫折磨難,但挫折磨難一定是我們靈魂與事業(yè)升起的層層...
    國仕空間閱讀 260評論 0 0