桥接模式

2021-04-14  本文已影响0人  lj72808up

桥接模式

  1. 思想: 组合优于继承

  2. 桥接模式有2种理解角度

    • 将业务的抽象和业务的具体实现分开
    • 当一个类存在2个以上的变化维度时, 通过组合, 让两个维度可以独立进行扩展
  3. jdbc 就是使用桥接模式实现不同数据库的操作的

    • 如下代码, 是 jdbc 的标准使用代码
    Class.forName("com.mysql.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 数据库换成 Oracle 数据库,只需要把第一行代码中的 com.mysql.jdbc.Driver 换成 oracle.jdbc.driver.OracleDriver 就可以了. 为什么可以这样呢? 原因在 com.mysql.jdbc.Driver 这个类
    package com.mysql.jdbc;
    public class Driver extends NonRegisteringDriver implements java.sql.Driver {
      static {
        try {
          java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
          throw new RuntimeException("Can't register driver!");
        }
      }
    
      /**
       * Construct a new driver and register it with DriverManager
       * @throws SQLException if a database error occurs.
       */
      public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
      }
    }
    

    我们可以发现,当执行 Class.forName(“com.mysql.jdbc.Driver”) 这条语句的时候,实际上是做了两件事情。
    * 第一件事情是要求 JVM 查找并加载指定的 Driver 类
    * 第二件事情是执行该类的静态代码块,也就是将自己 mysql.Driver 注册到 DriverManager 类中。

    经过以上分析返现, 各数据库自己的驱动注册到 DriverManager 后, 就能实现不同数据库自己的操作. DriverManager 就是业务的抽象, mysql.Driver
    就是业务的实现. 可以看到, DriverManager.getConnection 组合了 Driver.connect() 方法

    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()));
      }
      //...
    }
    
  1. 假设要实现一个 API 接口监控告警的例子:根据不同的告警规则,触发不同类型的告警。
    • 告警渠道有多个, 包括:邮件、短信、微信、自动语音电话。
    • 告警的紧急程度有个,包括:SEVERE(严重)、URGENCY(紧急)、NORMAL(普通)、TRIVIAL(无关紧要)。
      因为告警这个动作有2个变化维度: 渠道和严重程度. 因此可以把2个维度的协作方式作为业务的抽象, 2个维度各自的执行作为业务的具体实现
// 业务的具体实现
interface MsgSender {
    void send(String message);
}

class TelephoneMsgSender implements MsgSender {
    private List<String> telephones;
    public TelephoneMsgSender(List<String> telephones) {
        this.telephones = telephones;
    }

    @Override
    public void send(String message) {
        //...
    }
}

class EmailMsgSender implements MsgSender {
    // 与TelephoneMsgSender代码结构类似,所以省略...
}

class WechatMsgSender implements MsgSender {
    // 与TelephoneMsgSender代码结构类似,所以省略...
}


// 业务的抽象
abstract class Notification {
    protected MsgSender msgSender;

    public Notification(MsgSender msgSender) {
        this.msgSender = msgSender;
    }

    public abstract void notify(String message);
}

class SevereNotification extends Notification {
    public SevereNotification(MsgSender msgSender) {
        super(msgSender);
    }

    @Override
    public void notify(String message) {
        msgSender.send(message);
    }
}

class UrgencyNotification extends Notification {
    // 与SevereNotification代码结构类似,所以省略...
}
class NormalNotification extends Notification {
    // 与SevereNotification代码结构类似,所以省略...
}
class TrivialNotification extends Notification {
    // 与SevereNotification代码结构类似,所以省略...
}
上一篇下一篇

猜你喜欢

热点阅读