在變幻的時光中,狀態如詩篇般細膩流轉。
文章目錄
- 一、可調節的燈光
- 二、狀態模式
- 三、狀態模式的核心組件
- 四、運用狀態模式
- 五、狀態模式的應用場景
- 六、小結
- 推薦閱讀
一、可調節的燈光
場景假設:我們有一個電燈,它可以被打開和關閉。用戶可以通過一個開關來改變電燈的狀態。
/*** 表示可以開關的燈的類。*/
public class Light {private String state; // 燈的當前狀態,可能是"ON"或者"OFF"/*** 構造方法,初始化燈的狀態為"OFF"。*/public Light() {this.state = "OFF";}/*** 開關燈的狀態。* 如果燈當前為"OFF",則將其改為"ON"并打印"燈已打開"。* 如果燈當前為"ON",則將其改為"OFF"并打印"燈已關閉"。*/public void switchState() {if ("OFF".equals(state)) {state = "ON";System.out.println("燈已打開");} else {state = "OFF";System.out.println("燈已關閉");}}
}
上面的代碼雖然能夠實現需求,因為只有兩種狀態。但是,如果電燈有更多的狀態,比如“調暗”、“調亮”、“閃爍”等,那么 switchState 方法就會變得非常復雜,充滿了 if-else 語句。這將使代碼難以閱讀和維護。
二、狀態模式
狀態模式(State Pattern)是一種行為型
設計模式,它允許對象在其內部狀態發生改變時改變其行為,使其看起來像是改變了其類。狀態模式的關鍵思想是將對象的行為封裝在不同的狀態對象中,并且在狀態轉換時可以動態地改變對象的行為。
三、狀態模式的核心組件
狀態模式的核心組件包括以下幾個角色:
- Context(上下文):上下文是擁有狀態的對象。它定義了客戶端感興趣的接口,并且維護一個當前狀態對象,這個狀態對象定義了當前的狀態和相應的行為。Context 可以通過狀態對象來改變它的行為。
- State(狀態):狀態是一個接口或者抽象類,它封裝了與 Context 的一個特定狀態相關的行為。在 State 接口或者抽象類中定義了所有具體狀態類所共享的方法,這些方法的實現將依賴于當前狀態。通常,這些方法處理與狀態相關的操作,如請求或者事件。
- ConcreteState(具體狀態):具體狀態類實現了 State 接口或者繼承了 State 抽象類。每個具體狀態類實現了與 Context 的一個狀態相關的行為。例如,在電梯系統中,可能會有開門狀態、關門狀態、運行狀態和停止狀態等具體狀態類。
這個類圖展示了狀態模式的核心組成部分:
- State 接口定義了 doAction(Context) 方法,表示所有具體狀態類(OpenState 和 CloseState)需要實現的方法。
- OpenState 和 CloseState 類分別實現了 State 接口,并實現了 doAction(Context) 方法來處理具體的狀態操作。
- Context 類包含一個狀態接口類型的私有成員變量 state,通過 setState(State) 方法設置當前的狀態,并通過 request() 方法執行當前狀態的動作。
四、運用狀態模式
場景假設:我們有一個電燈,它可以被打開和關閉。用戶可以通過一個開關來改變電燈的狀態。電燈有更多的狀態,比如“調暗”、“調亮”、“閃爍”等。
-
定義狀態接口:首先,我們需要定義一個狀態接口,該接口聲明了所有具體狀態類需要實現的方法。在我們的例子中,我們可以定義一個 LightState 接口,該接口有一個 switchState 方法。
// 定義狀態接口 public interface LightState {// 聲明改變狀態的方法,接收一個 Light 對象作為參數void switchState(Light light); }
-
創建具體狀態類:然后,我們需要為每種狀態創建一個具體的狀態類。這些類需要實現狀態接口,并實現接口中聲明的方法。在我們的例子中,我們可以創建 OnState 和 OffState 類。
// 創建具體狀態類:打開狀態 public class OnState implements LightState {@Overridepublic void switchState(Light light) {// 改變 Light 對象的狀態為 DimStatelight.setState(new DimState());System.out.println("Light is dimmed");} }// 創建具體狀態類:關閉狀態 public class OffState implements LightState {@Overridepublic void switchState(Light light) {// 改變 Light 對象的狀態為 OnStatelight.setState(new OnState());System.out.println("Light is turned ON");} }// 創建具體狀態類:調暗狀態 public class DimState implements LightState {@Overridepublic void switchState(Light light) {// 改變 Light 對象的狀態為 BlinkStatelight.setState(new BlinkState());System.out.println("Light is blinking");} }// 創建具體狀態類:閃爍狀態 public class BlinkState implements LightState {@Overridepublic void switchState(Light light) {// 改變 Light 對象的狀態為 OffStatelight.setState(new OffState());System.out.println("Light is turned OFF");} }
-
在上下文類中使用狀態:最后,我們需要在上下文類中使用這些狀態。上下文類維護一個對狀態對象的引用,該引用可以在運行時更改。在我們的例子中,Light 類就是上下文類。
// 創建上下文類:電燈 public class Light {// Light 對象維護一個對狀態對象的引用private LightState state;public Light() {// 初始狀態為 OffStatethis.state = new OffState();}// 設置 Light 對象的狀態public void setState(LightState state) {this.state = state;}// 切換 Light 對象的狀態public void switchState() {state.switchState(this);} }
-
客戶端:通過客戶端測試
public class Client {public static void main(String[] args) {// 創建一個 Light 對象Light light = new Light();// 切換 Light 對象的狀態light.switchState(); // 打開電燈light.switchState(); // 調暗電燈light.switchState(); // 電燈開始閃爍light.switchState(); // 關閉電燈} }
五、狀態模式的應用場景
狀態模式在許多場景中都非常有用,特別是當一個對象的行為取決于其狀態,并且它必須在運行時根據狀態改變其行為時。以下是一些常見的應用場景:
- 用戶界面(UI):在許多用戶界面中,元素的行為會根據其狀態(如禁用、選中、懸停等)而改變。狀態模式可以幫助我們管理這些狀態,并使狀態轉換的邏輯更加清晰。
- 游戲開發:在游戲開發中,角色的行為通常會根據其狀態(如站立、跑動、跳躍、攻擊等)而改變。使用狀態模式,我們可以為每種狀態創建一個狀態類,使得代碼更易于理解和維護。
- 工作流引擎:在工作流引擎中,任務的行為會根據其狀態(如新建、進行中、已完成等)而改變。狀態模式可以幫助我們管理這些狀態,并使狀態轉換的邏輯更加清晰。
- 網絡連接:網絡連接的行為會根據其狀態(如打開、關閉、等待等)而改變。狀態模式可以幫助我們管理這些狀態,并使狀態轉換的邏輯更加清晰。
六、小結
狀態模式是一種優秀的設計模式,適用于那些對象行為會隨著內部狀態變化而變化的情況。它通過將對象的狀態和行為分離,使得系統更加靈活、易于理解和擴展。
推薦閱讀
- 深入探究 Spring Boot Starter:從概念到實踐
- 深入理解 Java 中的 volatile 關鍵字
- OAuth 2.0:現代應用程序的授權標準
- Spring 三級緩存
- 深入了解 MyBatis 插件:定制化你的持久層框架