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

重構實戰:以狀態模式消除冗長 if-else 鏈

     編輯:Java 相關知識

問題場景:充斥條件判斷的狀態管理

歷史系統常因語言限制而大量濫用 if-else,導致程式碼難以維護。本文以一個會議管理系統的 SystemManager 為例,示範如何透過重構將其轉化為物件導向設計,並引入測試保護。

原始碼痛點

public class SystemManager {
    public static final int LOGGEDIN = 0;
    public static final int LOGGEDOUT = 1;
    public static final int IDLE = 2;
    int state;

    public void updateState(int state) {
        if (state == LOGGEDIN) { /* ... */ }
        else if (state == LOGGEDOUT) { /* ... */ }
        else if (state == IDLE) { /* ... */ }
        else { throw new IllegalArgumentException("unknown state"); }
        this.state = state;
    }
}

隨狀態增加,if-else 將持續膨脹,違反開放封閉原則。

重構步驟演進

第一階段:建立安全網——編寫測試

使用 JUnit 編寫 SystemManagerTest,驗證 login()、logout()、idle() 狀態轉換。測試通過後方可放心重構。

第二階段:以 Enum 取代 int 常數

public enum SystemState { LOGGEDIN, LOGGEDOUT, IDLE }

將 state 欄位型別改為 SystemState,更新方法簽名與測試碼。此步驟提升型別安全,但 updateState 內的條件判斷仍存在。

第三階段:引入狀態執行者,多態替代條件判斷

核心洞見:updateState 需要針對不同 Enum 執行不同邏輯,因 Enum 本身無行為。解決方案是建立抽象類別 SystemStatePerformer,每個子類別負責一種狀態的具體行為。

public abstract class SystemStatePerformer {
    private final SystemState state;
    private Image image;
    public SystemStatePerformer(SystemState state, Image image) { ... }
    public abstract void perform();
}

工廠 + 匿名類別管理具體實作

避免為每個狀態建立獨立類別類,採用 Factory 方法回傳匿名內部類:

public class SystemStatePerformerFactory {
    private static SystemStatePerformerFactory INSTANCE = new SystemStatePerformerFactory();
    public static SystemStatePerformer getSystemStatePerformer(SystemState state) {
        switch (state) {
            case LOGGEDIN: return createLoggedInPerformer();
            case IDLE: return createIdlePerformer();
            case LOGGEDOUT: return createLoggedOutPerformer();
            default: throw new IllegalAccessError("Unknown status");
        }
    }
    private static SystemStatePerformer createLoggedInPerformer() {
        return new SystemStatePerformer(LOGGEDIN, getImage("loggedin.gif")) {
            @Override public void perform() { /* 登入後邏輯 */ }
        };
    }
    // ... 其他 createXxxPerformer 方法
}

重構 SystemManager

public class SystemManager {
    SystemStatePerformer statePerformer;
    public void updateState(SystemState state) {
        this.statePerformer = SystemStatePerformerFactory.getInstance().getSystemStatePerformer(state);
        statePerformer.perform(); // 多態調用,if-else 消失
    }
}

同步更新測試碼,驗證 statePerformer.getState()。

第四階段:徹底移除 Switch——Map 快取與反射掃描

Factory 內仍有 switch,本質同 if-else。改進:啟動時透過反射掃描標註 @FactoryMethod 的方法,建立所有 Performer 實例並存入 Map<SystemState, SystemStatePerformer>,查詢時直接 map.get(state),實現 O(1) 查找並完全移除條件分支。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FactoryMethod {}

設計模式對照與總結

此重構對應《Refactoring to Patterns》第七章「Replace Conditional Dispatcher with Command」,但有兩點創新:

  1. Factory + 匿名類別 替代每個狀態一個具體類,大幅減少類別數量與關聯複雜度。
  2. Performer 擁有狀態(如圖示),不只是無狀態的 Command,能封裝更豐富邏輯。

重構後代碼符合里氏替換原則 (LSP),子類別可完全替換基類別,系統更具擴展性與可維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved