1、什么是橋接模式?
Decouple an abstraction from its implementation so that the two can vary independently.
橋接模式(Bridge Pattern):將抽象和實現(xiàn)解耦, 使得兩者可以獨立地變化。
另外一種解釋是:一個類存在兩個(或多個)獨立變化的維度,我們通過組合的方式,讓這兩個(或多個)維度可以獨立進行擴展。
聽起來可能還是很深奧,沒關系,下面通過例子講解。
2、橋接模式定義
①、Abstraction
抽象化角色:它的主要職責是定義出該角色的行為, 同時保存一個對實現(xiàn)化角色的引用, 該角色一般是抽象類。
②、Implementor
實現(xiàn)化角色:它是接口或者抽象類, 定義角色必需的行為和屬性。
③、RefinedAbstraction
修正抽象化角色:它引用實現(xiàn)化角色對抽象化角色進行修正。
④、ConcreteImplementor
具體實現(xiàn)化角色:它實現(xiàn)接口或抽象類定義的方法和屬性。
3、橋接模式通用代碼實現(xiàn)
實現(xiàn)化類:
public interface Implementor {
void doSomething();
}
具體實現(xiàn)化類:
public class ConcreteImplementor1 implements Implementor{
@Override
public void doSomething() {
// 具體業(yè)務邏輯處理
}
}
public class ConcreteImplementor2 implements Implementor{
@Override
public void doSomething() {
// 具體業(yè)務邏輯
}
}
這里定義了兩個,可能有多個。
抽象化角色:
public abstract class Abstraction {
// 定義對實現(xiàn)化角色的引用
private Implementor implementor;
public Abstraction(Implementor implementor){
this.implementor = implementor;
}
// 自身的行為和屬性
public void request(){
this.implementor.doSomething();
}
// 獲取實現(xiàn)化角色
public Implementor getImplementor(){
return implementor;
}
}
修正抽象化角色:
public class RefinedAbstraction extends Abstraction{
// 覆寫構造函數(shù)
public RefinedAbstraction(Implementor implementor){
super(implementor);
}
// 修正父類的行為
@Override
public void request() {
super.request();
}
}
測試:
public class BridgeClient {
public static void main(String[] args) {
// 定義一個實現(xiàn)化角色
Implementor implementor = new ConcreteImplementor1();
// 定義一個抽象化角色
Abstraction abstraction = new RefinedAbstraction(implementor);
// 執(zhí)行方法
abstraction.request();
}
}
如果我們的實現(xiàn)化角色有很多的子接口, 然后是一堆的子實現(xiàn)。在構造函數(shù)中傳遞一個明確的實現(xiàn)者, 代碼也是很清晰的。
4、橋接模式經(jīng)典例子—JDBC
我們在剛開始用 JDBC 直連數(shù)據(jù)庫的時候,會有這樣一段代碼:
Class.forName("com.mysql.cj.jdbc.Driver");//加載及注冊JDBC驅動程序
String url = "jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password";
Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();
String query = "select * from test";
ResultSet rs=stmt.executeQuery(query);
while(rs.next()) {
rs.getString(1);
rs.getInt(2);
}
如果我們想要把 MySQL 數(shù)據(jù)庫換成 Oracle 數(shù)據(jù)庫,只需要把第一行代碼中的 com.mysql.cj.jdbc.Driver 換成oracle.jdbc.driver.OracleDriver 就可以了。
這種優(yōu)雅的實現(xiàn)數(shù)據(jù)庫切換方式就是利用了橋接模式。
我們首先看 Driver 類:
package com.mysql.cj.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
這段代碼 Class.forName("com.mysql.cj.jdbc.Driver") 作用有兩個:
①、要求 JVM 查找并加載指定的 Driver 類。
②、執(zhí)行該類的靜態(tài)代碼,也就是將 MySQL Driver 注冊到 DriverManager 類中。
接著我們看 DriverManager 類:
public class DriverManager {
private final static CopyOnWriteArrayList< DriverInfo > registeredDrivers = new CopyOnWriteArrayList< DriverInfo >();
//...
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
//...
public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException {
if (driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver));
} else {
throw new NullPointerException();
}
}
public static Connection getConnection(String url, String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties();
if (user != null) {
info.put("user", user);
}
if (password != null) {
info.put("password", password);
}
return (getConnection(url, info, Reflection.getCallerClass()));
}
//...
}
當我們把具體的 Driver 實現(xiàn)類(比如,com.mysql.cj.jdbc.Driver)注冊到 DriverManager 之后,后續(xù)所有對 JDBC 接口的調(diào)用,都會委派到對具體的 Driver 實現(xiàn)類來執(zhí)行。而 Driver 實現(xiàn)類都實現(xiàn)了相同的接口(java.sql.Driver ),這也是可以靈活切換 Driver 的原因。
5、橋接模式優(yōu)點
①、抽象和實現(xiàn)分離
這也是橋梁模式的主要特點, 它完全是為了解決繼承的缺點而提出的設計模式。在該模式下, 實現(xiàn)可以不受抽象的約束, 不用再綁定在一個固定的抽象層次上。
②、優(yōu)秀的擴充能力
看看我們的例子, 想增加實現(xiàn)?沒問題!想增加抽象, 也沒有問題!只要對外暴露的接口層允許這樣的變化, 我們已經(jīng)把變化的可能性減到最小。
③、實現(xiàn)細節(jié)對客戶透明
客戶不用關心細節(jié)的實現(xiàn), 它已經(jīng)由抽象層通過聚合關系完成了封裝。
6、橋接模式應用場景
①、如果一個系統(tǒng)需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的繼承聯(lián)系,通過橋接模式可以使它們在抽象層建立一個關聯(lián)關系。
②、對于那些不希望使用繼承或因為多層次繼承導致系統(tǒng)類的個數(shù)急劇增加的系統(tǒng),橋接模式尤為適用。
③、一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。
-
接口
+關注
關注
33文章
8526瀏覽量
150861 -
數(shù)據(jù)庫
+關注
關注
7文章
3767瀏覽量
64279 -
函數(shù)
+關注
關注
3文章
4308瀏覽量
62444 -
代碼
+關注
關注
30文章
4753瀏覽量
68368 -
JDBC
+關注
關注
0文章
25瀏覽量
13393
發(fā)布評論請先 登錄
相關推薦
評論