1.1概述 允許一個對象在其內部狀態改變時改變它的行為,對象看起來似乎修改了它的類。這就是狀態模式的定義。 一個對象的狀態依賴於它的變數的取值情況,對象在不同的運行環境中,可能具有不同的狀態。在許多情況下,對象調用方法所產生的行為效果依賴於它當時的狀態。 例如,一個溫度計(Thermometer)類 ...
1.1概述
允許一個對象在其內部狀態改變時改變它的行為,對象看起來似乎修改了它的類。這就是狀態模式的定義。
一個對象的狀態依賴於它的變數的取值情況,對象在不同的運行環境中,可能具有不同的狀態。在許多情況下,對象調用方法所產生的行為效果依賴於它當時的狀態。
例如,一個溫度計(Thermometer)類的實例:溫度計類通過調用方法showMessage()顯示有關信息時,需要根據當前自己溫度(temperature)變數的值來顯示有關信息,即根據自己的狀態來決定showMessage()方法所體現的具體行為,這就要求showMessage()方法中有許多條件分支語句,例如:
public void showMessage(){ if(temperature <= -20){ System.out.println("現在是低溫"+temperature); } if(temperature >= 30){ System.out.println("現在是高溫"+temperature); } }
我們註意到showMessage()方法的行為依賴於temperature的大小,這就使Thermometer類的實例在應對需求變化時缺乏彈性,不能很好地滿足用戶的需求。例如,有些用戶可能需要溫度計當其temperature的值大於60顯示某些重要的信息;有些用戶當其溫度temperature的值在18到25之間顯示重要的信息。顯然為達到上述要求,必須修改上面的代碼才可以滿足用戶需求,者顯然不是人們喜歡做的。
現在我們需要重新考慮溫度計(Thermometer)類的設計,發現溫度計類中因用戶需求變化而需要修改的代碼都和對象的狀態有關,即與溫度的大小有關,因此,按照面向抽象、不面向實現的設計原則,應當將對象的狀態從當前對象中分離出去,即將一個對象的狀態封裝在另外一個類中。現在,設計一個抽象類:TemperatureState類,該類規定了顯示和溫度有關的信息的方法showTemperature()。具體類關係圖如下圖一所示:
圖一:封裝對象的狀態
Thermometer類包含ThermometerState類聲明的若幹個變數,錶面Thermometer類的實例:溫度計類可以將任何溫度計狀態類的子類的實例作為自己的狀態,而且溫度計類的實例可以把和狀態有關的請求委派給所維護狀態的對象。
狀態模式的關鍵是將對象的狀態封裝成為獨立的類,對象調用方法時,可以委托當前對象所具有的狀態調用相應的方法,是當前對象看起來好像修改了它的類。
1.2模式的結構
狀態模式包括以下三種角色:
(1)環境(Context):環境是一個類,該類含有抽象狀態(State)聲明的變數,可以引用任何具體狀態類的實例。用戶對該環境(Context)類的實例在某種狀態下的行為感興趣。
(2)抽象狀態(State):抽象狀態是一個介面或抽象類。抽象狀態中定義了與環境(Context)的一個特定狀態相關的若幹個方法。
(3)具體狀態(Concrete State):具體狀態是實現(擴展)抽象狀態(抽象類)的實例。
狀態模式結構的類圖如下圖二所示:
圖二:狀態模式的類圖
1.3狀態模式的優點
(1)使用一個類封裝對象的一種狀態,很容易增加新的狀態。
(2)在狀態模式中,環境(Context)中不必出現大量的條件判斷語句。環境(Context)實例所呈現的狀態變得更加清晰、容易理解。
(3)使用狀態模式可以讓用戶程式很方便地切換環境實例的狀態。
(4)使用狀態模式不會讓環境的實例中出現內部狀態不一致的情況。
(5)當狀態對象沒有實例變數時,環境的各個實例可以共用一個狀態對象。
1.4適合使用狀態模式的情景
(1)一個對象的行為依賴於它的狀態,並且它必須在運行時根據狀態改變它的行為。
(2)需要編寫大量的條件分支語句來決定一個操作的行為,而且這些條件恰好表示對象的一種狀態。