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

Java 策略模式實戰:圖片儲存格式動態切換

     編輯:Java 程式設計入門

策略模式將演算法族群封裝為可互換的策略類別,讓客戶端在執行期動態選擇行為,避免龐大的 if-else 或 switch。本文以「圖片儲存格式選擇」為例,展示標準實作與現代化改良。

核心角色

  • Strategy (ImageSaver):定義統一介面 save()。
  • ConcreteStrategy (GIFSaver, JPEGSaver, PNGSaver):具體演算法實作。
  • Context (TypeChooser):持有策略引用,對客戶端暴露統一入口。
  • Client (User):根據輸入決定使用哪個策略。

標準實作 (Java 7 風格)

// 1. 策略介面
public interface ImageSaver {
    void save();
}

// 2. 具體策略
public class GIFSaver implements ImageSaver {
    @Override public void save() { System.out.println("儲存為 GIF 格式"); }
}
public class JPEGSaver implements ImageSaver {
    @Override public void save() { System.out.println("儲存為 JPEG 格式"); }
}
public class PNGSaver implements ImageSaver {
    @Override public void save() { System.out.println("儲存為 PNG 格式"); }
}

// 3. Context:策略選擇與委派
public class TypeChooser {
    public static ImageSaver getSaver(String type) {
        switch (type.toUpperCase()) {
            case "GIF":  return new GIFSaver();
            case "JPEG": return new JPEGSaver();
            case "PNG":  return new PNGSaver();
            default:     throw new IllegalArgumentException("不支援格式: " + type);
        }
    }
}

// 4. 客戶端使用
public class User {
    public static void main(String[] args) {
        ImageSaver saver = TypeChooser.getSaver("GIF");
        saver.save();  // 輸出: 儲存為 GIF 格式
    }
}

進階改良:Java 8+ 函數式風格

利用 Map> 消除 switch,支援熱插拔:

public class TypeChooserV2 {
    private static final Map> REGISTRY = new HashMap<>();

    static {
        REGISTRY.put("GIF",  GIFSaver::new);
        REGISTRY.put("JPEG", JPEGSaver::new);
        REGISTRY.put("PNG",  PNGSaver::new);
    }

    public static ImageSaver getSaver(String type) {
        Supplier supplier = REGISTRY.get(type.toUpperCase());
        if (supplier == null) throw new IllegalArgumentException("不支援: " + type);
        return supplier.get();
    }

    // 支援運行期註冊新格式 (如外掛機制)
    public static void register(String type, Supplier supplier) {
        REGISTRY.put(type.toUpperCase(), supplier);
    }
}

Spring 整合:策略 Bean 自動註冊

@Component
public class ImageSaverFactory {
    private final Map savers = new HashMap<>();

    @Autowired
    public ImageSaverFactory(List saverList) {
        for (ImageSaver s : saverList) {
            String key = s.getClass().getSimpleName().replace("Saver", "").toUpperCase();
            savers.put(key, s);
        }
    }

    public ImageSaver getSaver(String type) {
        ImageSaver s = savers.get(type.toUpperCase());
        if (s == null) throw new IllegalArgumentException("不支援: " + type);
        return s;
    }
}

// 每個策略獨立 Bean
@Component("GIF")  public class GIFSaver  implements ImageSaver { ... }
@Component("JPEG") public class JPEGSaver implements ImageSaver { ... }
@Component("PNG")  public class PNGSaver  implements ImageSaver { ... }

策略模式 vs 狀態模式 vs 模板方法

模式核心意圖關鍵差異
策略模式演算法可互換,客戶端主動選擇策略之間平行無關,Context 不持有狀態
狀態模式物件行為隨內部狀態改變狀態轉換通常由 Context 或 State 內部控制
模板方法定義演算法骨架,子類實作細節繼承關係,編譯期固定流程

適用場景檢核表

  • [ ] 系統有多種方式完成同一操作 (壓縮、排序、付款、匯出格式)。
  • [ ] 需在運行期根據條件切換演算法。
  • [ ] 想避免大量條件判斷汙染核心邏輯。
  • [ ] 新增演算法不應修改既有代碼 (開放封閉原則)。

若以上均符合,策略模式是最佳選擇。

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