介面是 Java 實現「面向抽象編程」的核心工具。許多開發者僅停留在「定義方法簽名」的表層理解,忽略了介面在解耦合、擴展性、多態替換上的實戰威力。本文透過兩個經典案例,深度演示介面的精髓應用。
當業務邏輯需要支援「未知的未來擴充」時,介面提供了一個固定契約,新實作類別只需實現契約,無須修改既有代碼——這就是開閉原則(OCP)的具體體現。
需求:計算不同交通工具行駛 1000 公里所需時間。當前有 Car、Plane,未來可能新增 Ship、Train 等,要求核心計算邏輯零修改。
// 1. 契約介面
public interface Common {
double runTimer(double a, double b, double c);
}
// 2. 具體實作
public class Plane implements Common {
public double runTimer(double a, double b, double c) { return a + b + c; }
}
public class Car implements Common {
public double runTimer(double a, double b, double c) { return a * b / c; }
}
// 3. 核心邏輯:反射動態實例化
public class ComputeTime {
public static void main(String[] args) {
// args[0]=類別名, args[1..3]=參數 A,B,C
String vehicleClass = "CalTime.vehicle." + args[0];
double A = Double.parseDouble(args[1]);
double B = Double.parseDouble(args[2]);
double C = Double.parseDouble(args[3]);
try {
// 關鍵:Class.forName(...).newInstance() 動態載入
Common vehicle = (Common) Class.forName(vehicleClass).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");
}
}
}
java ComputeTime Plane 20 30 40 java ComputeTime Car 23 34 45 java ComputeTime Ship 22 33 44 // 新增 Ship.java 即可,ComputeTime 完全不動
Common vehicle 接收任何實作類別。場景:主機板擁有多種擴充槽,需支援鍵盤卡、網路卡等,未來可能新增聲音卡、顯示卡。
// 1. 擴充卡契約
interface Extendable {
void inPut();
}
// 2. 具體卡片
class KeyBoard implements Extendable {
public void inPut() { System.out.println("鍵盤卡已插入"); }
}
class NetCard implements Extendable {
public void inPut() { System.out.println("網路卡已插入"); }
}
// 3. 主機板:方法參數為介面型別
class MainBoard {
public void getMainMessage(Extendable card) {
card.inPut(); // 多態調用:實際執行具體卡片的 inPut()
}
}
// 4. 客戶端
public class InterfaceTest {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
mb.getMainMessage(new KeyBoard()); // 輸出: 鍵盤卡已插入
mb.getMainMessage(new NetCard()); // 輸出: 網路卡已插入
}
}
// 新增聲音卡,零修改既有代碼
class SoundCard implements Extendable {
public void inPut() { System.out.println("聲音卡已插入"); }
}
// 使用時直接傳入
mb.getMainMessage(new SoundCard());
| 維度 | 動態載入模式 | 參數傳遞模式 |
|---|---|---|
| 核心機制 | 反射 + 類別名稱外部化 | 多態參數 + 介面契約 |
| 解耦層級 | 編譯期完全不依賴具體類別 | 編譯期依賴介面,執行期傳入實作 |
| 適用場景 | 插件架構、驅動程式、熱插拔 | 策略模式、訪問者模式、回調處理 |
| 配置方式 | 配置檔、命令列、服務發現 | 依賴注入、工廠方法、直接 new |
介面不只是「方法簽名的集合」,它是系統擴展點的標準化契約。掌握「介面作為型別參數」與「反射動態載入」兩大模式,能讓您設計出真正符合開閉原則、經得起需求變更考驗的 Java 系統。