我們是否在寫程序的過程中有過在一個類中寫了很多狀態,是否需要根據該對象的不同狀態決定該對象的不同行為。如:我們Android中自定義一個上拉加載更多,下拉刷新的RefreshListView呢?,我們在RefreshListView中定義了三中狀態,即:下拉刷新狀態,正在刷新,松開刷新,而且這三中不同的狀態決定了該自定義控件是否可以下拉等行為,假如你沒定義過該控件或者沒有寫個那種一個對象有多種狀態對應控制多種行為也不要緊,因為狀態模式很簡單,我們只需要一個例子就知道怎么實現狀態模式了。
定義:當一個對象內部狀態改變時允許改變其行為,而不用根據不同的狀態做過多的if-else判斷,而是用不同的類代表不同狀態下的行為,這不同的類可以之間不用相互依賴,各自代表不同狀態下的行為。
狀態模式使用場景:
1.
一個對象的行為取決于它的狀態,并且需要在運行的時候根據不同的狀態改變行為。如:我們的RefreshListView,如果當前它的狀態是正在刷新,那么它就不可下拉
1.
代碼中包含大量與對象狀態相關的if-else語句,一個操作中含有大量的多分支語句if-else或者switch-case語句依賴于該對象的狀態的情況,如果是這種情況,那么代碼的可讀性不好,且不易修改維護。
狀態模式的優點:
- 使程序的可擴展提高,易于維護。狀態模式用一個狀態行為類代表一種狀態下個行為,擺脫了繁瑣的狀態判斷行為,將繁瑣的狀態判斷轉換成結構清晰的狀態類集。
狀態模式的缺點:
- 必然使得系統類和對象的個數增多。
代碼實現:
電視機行為接口:
~~~
/**
* 電視機行為
* @author lt
*
*/
public interface TvAction {
public void startUp(); // 開機
public void startOff(); // 關機
public void nextChannel(); // 下一個頻道
public void prevChannel(); // 上一個頻道
}
~~~
開機狀態行為:
~~~
/**
* 電視機開機狀態下的行為
* @author lt
*
*/
public class TvStartUpState implements TvAction{
/**
* 開機,無效
*/
@Override
public void startUp() {
}
/**
* 關機,有效
*/
@Override
public void startOff() {
System.out.println("關機啦!");
}
/**
* 下一個頻道,無效
*/
@Override
public void nextChannel() {
System.out.println("切換到下一個頻道");
}
/**
* 上一個頻道,無效
*/
@Override
public void prevChannel() {
System.out.println("切換到上一個頻道");
}
}
~~~
關機狀態行為:
~~~
/**
* 電視機關機狀態下的行為
* @author lt
*
*/
public class TvStartOffState implements TvAction{
/**
* 開機,有效
*/
@Override
public void startUp() {
System.out.println("開機啦!");
}
/**
* 關機,無效
*/
@Override
public void startOff() {
}
/**
* 下一個頻道,無效
*/
@Override
public void nextChannel() {
}
/**
* 上一個頻道,無效
*/
@Override
public void prevChannel() {
}
}
~~~
遙控器:
~~~
/**
* 遙控器
* @author lt
*
*/
public class TvController implements TvAction{
private TvAction tvStartUpState = new TvStartUpState();
private TvAction tvStartOffState = new TvStartOffState();
/**
* 電視機的狀態行為,狀態即行為,默認為關機狀態
*/
private TvAction tvState = tvStartOffState;
@Override
public void startUp() {
tvState.startUp();
this.tvState = tvStartUpState;
}
@Override
public void startOff() {
tvState.startOff();
this.tvState = tvStartOffState;
}
@Override
public void nextChannel() {
tvState.nextChannel();
}
@Override
public void prevChannel() {
tvState.prevChannel();
}
}
~~~
測試:
~~~
public class Test {
public static void main(String[] args) {
TvController tvController = new TvController();
// 開機
tvController.startUp();
tvController.nextChannel();
tvController.prevChannel();
// 關機
tvController.startOff();
tvController.nextChannel();
tvController.prevChannel();
// 開機
tvController.startUp();
// 關機
tvController.startOff();
}
}
~~~
結果:

狀態模式模擬結束,上面我們測試的時候,我們對電視機的狀態頻繁切換,并操作了對應狀態下的行為,達到了不同狀態下對象的行為改變了。但你是否在上面所有的代碼你有看到if-else或者switch-case?沒有吧,事實上,狀態模式就是為了避免過多的if-else和switch-case語句。上面模擬過程中我們看到了電視機的狀態行為切換如此簡單。
總結:
狀態模式的出現就是為了解決一個對象多種狀態下不同行為表現導致出現過多的if-else或者switch-case語句判斷切換不同狀態下的行為, 通常這種做法需要設置一個變量記錄該對象當前的狀態,然后根據變量執行不同的代碼。而狀態模式根本就不需要if-else和switch-case,一個對象類代表一種狀態下的行為表現,當狀態切換時切換不同的對象類即可,達到狀態即行為的效果。狀態模式的使用和沒有使用狀態模式的if-else/switch-case控制行為的關系有點像c是面向過程而java面向對象的關系一樣。