首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 設計模式實戰:狀態模式實現電視機開關與頻道控制

     編輯:Java 綜合教學

Java 設計模式實戰:狀態模式

狀態模式將對象行為封裝於獨立狀態類中,通過切換狀態對象實現行為動態變化,避免龐大的 if-else 分支。本文以電視機遙控器為例,完整展示接口定義、具體狀態實現、上下文控制類及測試驗證。

一、模式結構

狀態模式 UML
  • State(狀態介面):定義各狀態共同行為(換台、調音量)。
  • ConcreteState(具體狀態):實現介面,封裝特定狀態下的行為邏輯。
  • Context(環境/控制類):持有當前狀態引用,委派請求給狀態對象,負責狀態切換。

二、適用場景

  • 對象行為隨狀態頻繁變化,且狀態轉換邏輯固定。
  • 代碼中存在大量與狀態相關的 if-else/switch 分支。
  • 典型案例:訂單狀態流轉、TCP 連接狀態、遊戲角色狀態、UI 控件啟用/禁用。

三、代碼實現:電視機遙控器

1. 狀態介面

public interface TvState {
    void nextChannel();
    void prevChannel();
    void volumeUp();
    void volumeDown();
}

2. 開機狀態

public class PowerOnState implements TvState {
    @Override public void nextChannel() { System.out.println("---------下一頻道-----------------------"); }
    @Override public void prevChannel() { System.out.println("---------上一頻道-----------------------"); }
    @Override public void volumeUp() { System.out.println("---------音量增大-----------------------"); }
    @Override public void volumeDown() { System.out.println("---------音量減小-----------------------"); }
}

3. 關機狀態

public class PowerOffState implements TvState {
    @Override public void nextChannel() { System.out.println("---------關機狀態不可用,請先開機-----------------------"); }
    @Override public void prevChannel() { System.out.println("---------關機狀態不可用,請先開機-----------------------"); }
    @Override public void volumeUp() { System.out.println("---------關機狀態不可用,請先開機-----------------------"); }
    @Override public void volumeDown() { System.out.println("---------關機狀態不可用,請先開機-----------------------"); }
}

4. 控制類

public class TvController {
    private TvState tvState;
    private boolean isOn = false;

    public void setTvState(TvState tvState) { this.tvState = tvState; }

    public void turnOn() {
        if (!isOn) {
            isOn = true;
            setTvState(new PowerOnState());
            System.out.println("--------開機啦---------------");
        } else {
            System.out.println("--------已經開機了,不要再按了---------------");
        }
    }

    public void turnOff() {
        if (isOn) {
            isOn = false;
            setTvState(new PowerOffState());
            System.out.println("--------關機啦---------------");
        } else {
            System.out.println("-------已經關機啦,不要再按了---------------");
        }
    }

    // 委派給當前狀態
    public void nextChannel() { tvState.nextChannel(); }
    public void prevChannel() { tvState.prevChannel(); }
    public void volumeUp() { tvState.volumeUp(); }
    public void volumeDown() { tvState.volumeDown(); }
}

5. 測試驗證

public class TestClass {
    public static void main(String[] args) {
        TvController ctrl = new TvController();
        ctrl.turnOn();       // 開機
        ctrl.turnOn();       // 重複開機提示
        ctrl.nextChannel();  // 下一頻道
        ctrl.volumeDown();   // 音量減小
        ctrl.turnOff();      // 關機
        ctrl.turnOff();      // 重複關機提示
        ctrl.volumeDown();   // 關機後操作無效
    }
}

輸出:

--------開機啦---------------
--------已經開機了,不要再按了---------------
---------下一頻道-----------------------
---------音量減小-----------------------
--------關機啦---------------
-------已經關機啦,不要再按了---------------
---------關機狀態不可用,請先開機-----------------------

四、模式優勢總結

  1. 職責分離:控制類不處理具體行為,行為封裝於狀態類,符合單一職責原則。
  2. 開閉原則:新增狀態只需新增 State 實現類,無需修改 Context 與現有狀態類。
  3. 消除條件分支:將分散在各方法中的狀態判斷集中到狀態類內部。
  4. 狀態轉換顯式化:通過 setState 明確觸發轉換,便於追蹤與日誌記錄。

五、擴展建議

  • 引入 StateContext 接口,讓狀態類可反向觸發上下文狀態切換(如頻道鎖定自動關機)。
  • 結合枚舉實現有限狀態機(FSM),編譯期保證狀態完整性。
  • 狀態類可設計為單例(無狀態數據時),減少對象創建開銷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved