什麼是工廠模式?
用於隱藏對象創建的具體實現細節,讓程式設計可以專注於使用物件,而不需要知道物件是如何被創建的。這種模式的主要目的是透過「工廠」來管理物件的創建,提升程式的可擴展性與可維護性。
重構前
所有的邏輯都可以靠if-else 解決,如果不行就再加一層(?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class LogisticsService {
public void deliverPackage(String logisticsType, String packageId, String destination) { if ("express".equalsIgnoreCase(logisticsType)) { System.out.println("使用快遞物流運送,包裹編號:" + packageId + ",目的地:" + destination); } else if ("freight".equalsIgnoreCase(logisticsType)) { System.out.println("使用貨運物流運送,包裹編號:" + packageId + ",目的地:" + destination); } else if ("drone".equalsIgnoreCase(logisticsType)) { System.out.println("使用無人機物流運送,包裹編號:" + packageId + ",目的地:" + destination); } else { throw new RuntimeException("未知的物流類型:" + logisticsType); } } }
|
重構後
定義接口
1 2 3
| public interface Logistics { void deliver(String packageId, String destination); }
|
實現接口
- 貨運
1 2 3 4 5 6
| public class FreightLogistics implements Logistics { @Override public void deliver(String packageId, String destination) { System.out.println("使用貨運物流運送,包裹編號:" + packageId + ",目的地:" + destination); } }
|
- 快遞
1 2 3 4 5 6 7
| public class ExpressLogistics implements Logistics { @Override public void deliver(String packageId, String destination) { System.out.println("使用快遞物流運送,包裹編號:" + packageId + ",目的地:" + destination); } }
|
- 無人機
1 2 3 4 5 6
| public class DroneLogistics implements Logistics { @Override public void deliver(String packageId, String destination) { System.out.println("使用無人機物流運送,包裹編號:" + packageId + ",目的地:" + destination); } }
|
建立 Enum
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public enum LogisticsEnum { EXPRESS("express", new ExpressLogistics()), FREIGHT("freight", new FreightLogistics()), DRONE("drone", new DroneLogistics());
private final String type; private final Logistics logisticsService;
LogisticsEnum(String type, Logistics logisticsService) { this.type = type; this.logisticsService = logisticsService; }
public String getType() { return type; }
public Logistics getLogisticsService() { return logisticsService; }
public static Logistics getLogisticsByType(String logisticsType) { for (LogisticsEnum value : values()) { if (value.getType().equalsIgnoreCase(logisticsType)) { return value.getLogisticsService(); } } throw new IllegalArgumentException("未知的物流類型:" + logisticsType); } }
|
建立工廠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class LogisticsFactory {
public static Logistics getLogisticsService(String logisticsType) { return Arrays.stream(LogisticsEnum.values()) .filter(enumType -> enumType.getType().equalsIgnoreCase(logisticsType)) .findFirst() .map(LogisticsEnum::getLogisticsService) .orElseThrow(() -> new IllegalArgumentException("未知的物流類型:" + logisticsType)); } }
|
未來擴建
- Enum 內新增
1
| SEA("sea", new SeaLogistics())
|
- 建立實例
1 2 3 4 5 6 7 8
| public class SeaLogistics implements Logistics {
@Override public void deliver(String packageId, String destination) { System.out.println("使用海運物流運送,包裹編號:" + packageId + ",目的地:" + destination); } }
|
結論
這種方式保證了程式碼結構的清晰和擴展的便捷性,完全符合開放/封閉原則 (OCP)。
圖源/參考資料:
https://refactoring.guru/
重學java設計模式-小博哥