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

善用物件導向設計模式替換 Switch-Case 與 If-Else

     編輯:Java 相關知識

在日常 Java 開發中,針對狀態或類型進行判斷時,switch-case 與 if-else 是最直觀的寫法。然而,隨著業務邏輯增長,這類條件分支往往會膨脹成難以維護的「箭頭型代碼」。在物件導向的世界裡,我們有兩套經典方案能優雅地消除這些判斷:繼承多態與狀態模式。兩者的核心思想都是利用物件的間接引用,將條件分支分散到各個具體類別中,實現「開閉原則」——對擴展開放,對修改關閉。

問題場景:HTTP 方法的判斷邏輯

假設我們有一個 Method 類別,需根據型別(POST、GET、PUT、DELETE)執行不同邏輯:回傳描述字串、判斷是否為安全方法、判斷是否需要密碼。原始寫法如下:

public class Method {
    private int _type;
    public static final int POST = 0, GET = 1, PUT = 2, DELETE = 3;

    public Method(int type) { _type = type; }

    public String getMethod() {
        switch (_type) {
            case POST: return "This is POST method";
            case GET:  return "This is GET method";
            case PUT:  return "This is PUT method";
            case DELETE: return "This is DELETE method";
            default: throw new NoMethodTypeException();
        }
    }

    public boolean safeMethod() { return _type == GET; }
    public boolean passwordRequired() { return _type != POST; }
}

這裡存在一個 switch 和兩個 if-else,每次新增 HTTP 方法都必須修改這三個地方,違反單一職責原則。

方案一:繼承多態——適用於「物件生命週期中狀態不變」的場景

若一個 Method 物件一旦建立,其型別就不再改變,繼承多態是最自然的選擇。我們將 Method 定義為抽象基類,四種 HTTP 方法各自對應一個子類別:

類別圖:繼承多態結構

public abstract class Method {
    // 靜態工廠方法,隱藏具體子類別建立細節
    public final static Method createPostMethod() { return new PostMethod(); }
    public final static Method createGetMethod()  { return new GetMethod();  }
    public final static Method createPutMethod()  { return new PutMethod();  }
    public final static Method createDeleteMethod(){ return new DelMethod(); }

    abstract public String getMethod();

    // 預設實現符合大多數子類別,少數例外再 override
    public boolean safeMethod() { return false; }
    public boolean passwordRequired() { return true; }
}

public class PostMethod extends Method {
    @Override public String getMethod() { return "This is POST method"; }
    @Override public boolean passwordRequired() { return false; }
}

public class GetMethod extends Method {
    @Override public String getMethod() { return "This is GET method"; }
    @Override public boolean safeMethod() { return true; }
}

// PutMethod、DelMethod 僅需實作 getMethod(),沿用預設行為

優點:結構清晰,新增方法只需新增子類別,不動既有代碼。
適用性:物件狀態在生命週期內固定不可變。

方案二:狀態模式——適用於「物件需在運行時動態切換狀態」的場景

若同一個 Method 物件需要在運行期隨時切換 POST/GET/PUT/DELETE,繼承多態就無法滿足(Java 不支援物件動態換類)。此時引入 State 模式:將狀態抽象為介面,每種狀態一個實現類,Context 物件持有對當前狀態物件的引用,並委派行為給它。

類別圖:狀態模式結構

public interface MethodType {
    String getTypeDescription();
    String getMethodDescription();
    boolean isSafe();
    boolean isRequired();
}

public class Post implements MethodType { /* 實作四個介面方法 */ }
public class Get  implements MethodType { /* 實作四個介面方法 */ }
public class Put  implements MethodType { /* 實作四個介面方法 */ }
public class Delete implements MethodType { /* 實作四個介面方法 */ }

public class Method {
    private MethodType _type;
    public Method() { _type = null; }
    public Method(MethodType type) { _type = type; }

    public String getMethod() { return _type.getMethodDescription(); }
    public boolean safeMethod() { return _type.isSafe(); }
    public boolean passwordRequired() { return _type.isRequired(); }

    // 運行時動態切換狀態
    public void changeType(MethodType type) { _type = type; }

    public void runAllMethods() {
        MethodType[] types = { new Post(), new Get(), new Put(), new Delete() };
        for (MethodType t : types) {
            System.out.println(t.getTypeDescription());
            changeType(t);
            System.out.println(getMethod());
            System.out.println(safeMethod());
            System.out.println(passwordRequired());
        }
    }
}

優點:狀態切換靈活,符合「組合優於繼承」原則。
適用性:物件需在生命週期中頻繁變更行為。

總結與選型建議

  • 狀態固定:優先用繼承多態,代碼更簡潔,效能略優(無額外委派)。
  • 狀態可變:必須用狀態模式,將狀態封裝為獨立物件,支援運行時熱插拔。
  • 兩種方案都將「判斷邏輯」轉移為「物件結構」,消除了集中式的 switch/if,讓系統更易擴展、測試與維護。

完整測試代碼請參考原文中的 Client.java,三種實現輸出結果完全一致,驗證了重構的正確性。

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