為研究所開發通用計算程式:輸入交通工具類型與三個整數參數 A、B、C,計算其行駛 1000 公里所需時間。現有 Car(速度 = A×B/C)與 Plane(速度 = A+B+C)兩類工具,要求新增工具類型時零修改既有代碼,僅需新增實現類。
核心在於定義統一契約介面 Common,主程式 ComputeTime 透過 Class.forName() 依參數動態實例化具體實現,實現開放封閉原則(OCP)。
CalTime/
├── ComputeTime.java # 主程式(預設套件)
└── vehicle/
├── all/
│ └── Common.java # 介面定義
└── *.java # Car.java, Plane.java 等實現類
package CalTime.vehicle.all;
public interface Common {
/** 計算速度(km/h) */
double runTimer(double a, double b, double c);
}
// Plane.java
package CalTime.vehicle;
import CalTime.vehicle.all.Common;
public class Plane implements Common {
@Override
public double runTimer(double a, double b, double c) {
return a + b + c; // 速度公式:A+B+C
}
}
// Car.java
package CalTime.vehicle;
import CalTime.vehicle.all.Common;
public class Car implements Common {
@Override
public double runTimer(double a, double b, double c) {
return a * b / c; // 速度公式:A*B/C
}
}
import CalTime.vehicle.all.Common;
public class ComputeTime {
public static void main(String[] args) {
// 參數檢查省略(生產環境必加)
System.out.println("交通工具: " + args[0]);
System.out.println(" 參數A: " + args[1]);
System.out.println(" 參數B: " + args[2]);
System.out.println(" 參數C: " + args[3]);
double A = Double.parseDouble(args[1]);
double B = Double.parseDouble(args[2]);
double C = Double.parseDouble(args[3]);
try {
// 動態載入:包名 + 類名
String className = "CalTime.vehicle." + args[0];
Common vehicle = (Common) Class.forName(className).newInstance();
double speed = vehicle.runTimer(A, B, C);
double time = 1000 / speed;
System.out.println("平均速度: " + speed + " km/h");
System.out.println("運行時間:" + time + " 小時");
} catch (Exception e) {
System.out.println("class not found: " + e.getMessage());
e.printStackTrace(); // 建議列印堆疊追蹤
}
}
}
# 從 CalTime 根目錄編譯(依賴順序:介面 → 實現 → 主程式)
javac vehicle/all/Common.java
javac vehicle/*.java
javac ComputeTime.java
# 執行範例
java ComputeTime Plane 20 30 40 # 輸出:速度 90.0, 時間 11.11...
java ComputeTime Car 23 34 45 # 輸出:速度 17.35..., 時間 57.61...
僅需在 vehicle/ 下新增 Ship.java 實作 Common,無需修改 ComputeTime、Common 或既有實現類:
package CalTime.vehicle;
import CalTime.vehicle.all.Common;
public class Ship implements Common {
@Override
public double runTimer(double a, double b, double c) {
return (a + b) * c; // 自定義公式
}
}
編譯後即可執行:java ComputeTime Ship 22 33 44
Common 定義算法族,各實現類封裝具體算法,主程式動態切換策略。Class.forName().newInstance() 充當簡易反射工廠,根據字串參數創建實例。Common,而非具體類;具體類同樣依賴抽象。ClassNotFoundException、InstantiationException、IllegalAccessException、NumberFormatException 分別處理。ConcurrentHashMap 緩存。java.util.ServiceLoader)或 OSGi/JPMS 替代硬編碼包路徑。這個案例雖小,卻完整演示了「介面抽象 + 反射動態載入」實現插件化架構的核心技法。這正是 Spring、Dubbo 等框架實現模組熱插拔、條件裝配的基石之一。掌握此模式,能讓你的系統具備優雅的擴展性,從容應對業務變化。