在面向對象系統中,對象間的協作關係遠比對象內部實現更關鍵。類之間的通訊、模組間的交互,在系統設計初期即需確立穩定契約。然而許多開發者僅停留在「實現介面」的被動層面,缺乏「設計介面」的主動意識,導致:
本文深入剖析介面本質、設計原則、環境語境與組件模型,助你建立真正的「面向契約」架構思維。
介面 = 規範、約束、契約,而非單指 Java interface 關鍵字。
abstract class (含狀態與部分實現)。interface (純契約)。一個實體可實現多個抽象面。介面應盡可能小、專一,客戶不應依賴它不需要的方法。大介面導致實現類被迫實現無關方法,耦合度飆升。
// 違反 ISP:強迫所有實現類關心持久化、序列化、網路傳輸
interface UserService { save(); serialize(); sendOverNetwork(); }
// 遵循 ISP:拆分為獨立介面
interface UserRepository { save(User u); }
interface UserSerializer { byte[] serialize(User u); }
interface UserTransmitter { void send(User u); }
高層模組不應依賴低層模組,二者都應依賴抽象 (介面)。抽象不應依賴細節,細節應依賴抽象。
// 違反 DIP:Controller 直接依賴 MySQL 實現
class UserController { private MySqlUserDao dao = new MySqlUserDao(); }
// 遵循 DIP:Controller 依賴介面,具體實現由 DI 容器注入
class UserController {
private UserRepository repo;
@Autowired UserController(UserRepository repo) { this.repo = repo; }
}
@Deprecated 並提供遷移期。系統論視角:環境 = 介面所處的空間與外部影響因素總和。同一介面在不同語境下語義截然不同:
脫離環境談介面設計是空中樓閣。介面契約必須顯式包含環境假設:同步/非同步、事務語義、錯誤碼、超時、重試、安全上下文傳遞等。
組件 = Contract (介面契約) + Code (實現) + Configuration (配置/部署描述),三者缺一不可:
這正是 Spring/IoC 容器、OSGi、Dubbo、gRPC 等框架的核心運作模型。
| 誤區 | 正確理解 |
|---|---|
| 面向介面 = 不寫實現類 | 介面與實現共存,介面定義邊界,實現填充邊界。無實現的介面無意義。 |
| 面向介面 = 面向過程 | 面向過程關注流程步驟;面向介面關注模組邊界契約,兩者正交。 |
| 所有類都要有介面 | 僅對「跨邊界」協作點 (Service、Repository、Strategy、Plugin) 定義介面;內部實現類 (Entity、ValueObject、Helper) 無需介面。 |
| Java interface 就是全部 | 介面可表現為 Java interface、abstract class、WSDL、Protobuf、OpenAPI、甚至文檔協議。形式服務於語境。 |
面向介面編程,本質是「面向抽象契約編程」。它要求架構師像設計網路協議 (RFC) 一樣設計模組邊界:嚴謹定義語法、語義、約束與演進規則,而非隨意提取類的 public 方法湊成介面。唯有將「介面設計」上升為獨立、前置、持續的架構活動,系統才能獲得真正的鬆散耦合、可替換性與長期演進能力。下次動筆寫 interface 前,請先問自己:這是一個契約,還只是一組方法簽名?