在實際系統開發中,過度使用繼承導致類層次爆炸、維護困難是常見痛點。Java 單繼承限制更迫使開發者構建深層繼承鏈。Bridge 模式 正是為了解決「多維度變化」而生:將抽象部分(高層控制邏輯)與實現部分(具體操作細節)解耦,使二者可獨立演化。本文通過一個查詢系統的逐步重構,演示 Bridge 模式的自然誕生過程。
需求:支持「查詢客戶信息」與「查詢帳戶信息」兩類業務,數據分別存儲於總部 Oracle 與分公司 Sybase 兩種數據庫。初級寫法在 SearchAction 中雙層 if-else 判斷業務類型與數據庫類型,直接拼 SQL、獲取連接、執行查詢。缺點顯而易見:
識別出「數據庫操作」為變化維度,定義接口 SearchDB:
public interface SearchDB {
Vector searchFromDB(String sql);
}
提供 SearchDBOracleImpl、SearchDBSybaseImpl 兩種實現。引入 SearchFactory 根據 dbType 動態創建實例。Action 代碼簡化為:
SearchDB dao = SearchFactory.createSearch(dbType);
return dao.searchFromDB(sql);
成果:數據庫實現解耦,新增數據庫只需加實現類與工廠判斷,業務邏輯不變。體現「針對接口編程」與「組合優於繼承」。
觀察發現:無論查詢客戶還是帳戶,流程固定為「構建 SQL → 執行查詢 → 返回結果」。將此流程上抽為抽象類 SearchAction:
public abstract class SearchAction {
protected SearchDB dao;
protected SearchDB createSearchImpl(int dbType) {
return SearchFactory.createSearch(dbType);
}
protected abstract String buildSql(); // 子類實現具體 SQL
public final Vector executeQuery(int dbType) { // 模板方法
dao = createSearchImpl(dbType);
return dao.searchFromDB(buildSql());
}
}
具體業務類僅需實現 buildSql():
public class SearchCustomerAction extends SearchAction {
protected String buildSql() { return "SELECT * FROM Customer"; }
}
public class SearchAccountAction extends SearchAction {
protected String buildSql() { return "SELECT * FROM Account"; }
}
再引入 ActionFactory 根據 actionType 創建具體 Action。最終調用端極其簡潔:
SearchAction action = ActionFactory.createAction(actionType);
return action.executeQuery(dbType);
| 角色 | 重構對應 | 職責 |
|---|---|---|
| Abstraction (抽象) | SearchAction | 定義高層控制流程,持有 Implementor 引用 |
| RefinedAbstraction (修正抽象) | SearchCustomerAction, SearchAccountAction | 實現抽象方法,封裝具體業務差異 |
| Implementor (實現接口) | SearchDB | 聲明底層操作接口 |
| ConcreteImplementor (具體實現) | SearchDBOracleImpl, SearchDBSybaseImpl | 實現特定數據庫操作細節 |
Bridge 不等於「隨意拆分接口」。關鍵在於識別穩定的高層協議(抽象)與易變的底層實現(實現)。若系統僅有單一變化維度,或抽象與實現緊密綁定無獨立演化需求,直接繼承或策略模式可能更簡潔。