在介紹狀态模式之前,我們先來看這樣一個執行個體:你公司力排萬難終于獲得某個酒店的系統開發項目,并且最終落到了你的頭上。下圖是他們系統的主要工作(夠簡單)。

當你第一眼看到這個系統的時候你就看出來了這是一個狀态圖,每個框框都代表了房間的狀态,箭頭表示房間狀态的轉換。分析如下:房間有三個狀态:空閑、已預訂、已入住,狀态與狀态之間可以根據客戶的動作來進行轉換。定義每個狀态的值。
通過客戶的動作将每個狀态整合起來,對于這個“最簡單”的方式肯定是if…else if…else啦!是以這裡我們就通過動作将所有的狀态全面整合起來。分析得這裡有四個動作:預訂、入住、退訂、退房。如下:
對于上面的代碼你是否滿意呢?滿意那麼你就沒有必要往下看了,不滿意我們接着講。
正當你完成這個“複雜”if..else if …else時(我都寫了一會兒),你客戶說,我們需要将某些房間保留下來以作為備用(standbyState),于是你發現你悲劇了,因為你發現你要在所有的操作裡都要判斷該房間是否為備用房間。當你老大經過你身邊的時候發現你正在糾結怎麼改的時候,你老大就問你為什麼不換一個角度思考以狀态為原子來改變它的行為,而不是通過行為來改變狀态呢?于是你就學到了狀态模式。
在很多情況下,一個對象的行為取決于它的一個或多個變化的屬性,這些屬性我們稱之為狀态,這個對象稱之為狀态對象。對于狀态對象而已,它的行為依賴于它的狀态,比如你要預訂房間,那麼隻有當該房間為空閑時你才能預訂,你想入住該房間也隻有當你預訂了該房間或者該房間為空閑時。對于這樣的一個對象,當它在于外部事件産生互動的時候,其内部狀态就會發生改變,進而使得他的行為也随之發生改變。
那麼何為狀态模式呢?所謂狀态模式就是允許對象在内部狀态發生改變時改變它的行為,對象看起來好像修改了它的類。
下圖為狀态模式的UML圖。
狀态模式包含如下角色:
Context: 環境類。可以包括一些内部狀态。
State: 抽象狀态類。State定義了一個所有具體狀态的共同接口,任何狀态都實作這個相同的接口,這樣一來,狀态之間就可以互相轉換了。
ConcreteState: 具體狀态類。具體狀态類,用于處理來自Context的請求,每一個ConcreteState都提供了它對自己請求的實作,是以,當Context改變狀态時行為也會跟着改變。
依然是上面那個酒店的執行個體。對于該執行個體的UML圖如下:
首先是狀态接口:State
然後是房間類
然後是3個狀态類,這個三個狀态分别對于這:空閑、預訂、入住。其中空閑可以完成預訂和入住兩個動作,預訂可以完成入住和退訂兩個動作,入住可以退房。
最後是測試類
運作結果
1、封裝了轉換規則。
2、枚舉可能的狀态,在枚舉狀态之前需要确定狀态種類。
3、将所有與某個狀态有關的行為放到一個類中,并且可以友善地增加新的狀态,隻需要改變對象狀态即可改變對象的行為。
4、允許狀态轉換邏輯與狀态對象合成一體,而不是某一個巨大的條件語句塊。
5、可以讓多個環境對象共享一個狀态對象,進而減少系統中對象的個數。
1、狀态模式的使用必然會增加系統類和對象的個數。
2、狀态模式的結構與實作都較為複雜,如果使用不當将導緻程式結構和代碼的混亂。
3、狀态模式對“開閉原則”的支援并不太好,對于可以切換狀态的狀态模式,增加新的狀态類需要修改那些負責狀态轉換的源代碼,否則無法切換到新增狀态;而且修改某個狀态類的行為也需修改對應類的源代碼。
1、對象的行為依賴于它的狀态(屬性)并且可以根據它的狀态改變而改變它的相關行為。
2、代碼中包含大量與對象狀态有關的條件語句
1、狀态模式允許一個對象基于内部狀态而擁有不同的行為。
2、Context會将行為委托給目前狀态對象。
3、狀态模式對“開閉原則”支援不是很好。
PS:如果你覺得文章對你有所幫助,别忘了推薦或者分享,因為有你的支援,才是我續寫下篇的動力和源泉!
作者:chenssy。一個專注于【死磕 Java】系列創作的男人
出處:https://www.cnblogs.com/chenssy/p/3280212.html
作者個人網站:https://www.cmsblogs.com/。專注于 Java 優質系列文章分享,提供一站式 Java 學習資料
目前死磕系列包括:
1. 【死磕 Java 并發】:https://www.cmsblogs.com/category/1391296887813967872(已完成)
2.【死磕 Spring 之 IOC】:https://www.cmsblogs.com/category/1391374860344758272(已完成)
3.【死磕 Redis】:https://www.cmsblogs.com/category/1391389927996002304(已完成)
4.【死磕 Java 基礎】:https://www.cmsblogs.com/category/1411518540095295488
5.【死磕 NIO】:https://www.cmsblogs.com/article/1435620402348036096
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。