狀態模式
引言
狀態模式屬於對象創建型模式,其意圖是允許一個對象在其內部狀態改變時改變它的行爲,對象看起來似乎修改了他的類。比較常見的例子是在一個表示網絡連接的 類TCPConnection,一個TCPConnection對象的狀態處於若干不同的狀態之一:連接已經建立(Established),正在監聽, 連接已經關閉(closed)。當一個TCPConnection對象收到其他對象的請求時,他根據自身的狀態作出不同的反應。例如:一個Open請求的 結果依賴於該連接已關閉還是連接已建立狀態。State模式描述了TCPConnection如何在每一種狀態下表現出不同的行爲。這一種模式的關鍵思想 是引入了一個稱爲TCPState的抽象類表示網絡的連接狀態,TCPState類爲各種表示不同的操作狀態的字類聲明瞭一個公共接口。TCPState 的子類實現與特定的狀態相關的行爲。例如,TCPEstablished和TCPClosed類分別實現了特定於TCPConnection的連接已建立 狀態和連接已關閉狀態的行爲。
定義和結構
Context(環境,具有狀態的類)定義客戶感興趣的類。
A. 實例化所有狀態,並記錄當前狀態
B. 把自己作爲參數,傳遞給具體狀態類
C. 對外暴露的所有行爲接口,都以當前狀態實現即可。
public class Car { private State curState;
public State getCurState() { return curState; }
public void setCurState(State curState) { this.curState = curState; } public Car() { curState = new HighSpeedState(this); } public void stop() { curState.stopCar(); } } |
State
定義一個接口以封裝與Context的一個特定狀態相關的行爲。
定義狀態相關的所有接口
public interface State { public void stopCar(); } |
ConcreteState Subclasses(具體狀態子類)
每一個子類實現一個與Context的狀態相關的行爲。
實現所有行爲,並設定狀態改變。
public class HighSpeedState implements State { private Car car; public HighSpeedState(Car car) { this.car = car; } @Override public void stopCar() { // TODO Auto-generated method stub System.out.println("高速剎車,降檔"); car.setCurState(new MediumSpeedState(car)); car.getCurState().stopCar(); } } |
public class LowSpeedState implements State {
private Car car; public LowSpeedState(Car car) { this.car = car; } @Override public void stopCar() { // TODO Auto-generated method stub System.out.println("掛空檔,停車"); } } |
public class MediumSpeedState implements State { private Car car; public MediumSpeedState(Car car) { this.car = car; } @Override public void stopCar() { // TODO Auto-generated method stub System.out.println("剎車,降檔,掛空檔"); car.setCurState(new LowSpeedState(car)); car.getCurState().stopCar(); } } |
客戶端
public class MyTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Car car=new Car(); car.stop(); } } |
他們的協作關係是:
- Context將於狀態相關的請求委託給當前的ConcreteState對象處理。
- Context可將自身作爲一個參數傳遞給處理該請求的狀態對象,這使得狀態對象在必要的時候可訪問Context。
- Context是客戶使用的主要接口,客戶可用狀態對象來配置一個Context,一旦一個Context配置完畢,他的客戶不再需要直接與狀態對象打交道。
- Context或者ConcreteState子類都可以決定哪個狀態是另外那個狀態的後繼者,以及是在何種條件下進行狀態轉換。
總結
前提條件
使用狀態模式的對象要具有不同的狀態屬性,切該對象有一系列動作會引起狀態改變。
適用情況
1) 一個對象的具體行爲取決於它的當前狀態, 也就是說它必須在運行時刻根據狀態來確定它的行爲,且行爲的變化會引起狀態的改變。
2) 一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。