Java设计模式之(六)——桥接模式
1、什么是桥接模式?
Decouple an abstraction from its implementation so that the two can vary independently.
桥接模式(Bridge Pattern):将抽象和实现解耦, 使得两者可以独立地变化。
另外一种解释是:一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。
听起来可能还是很深奥,没关系,下面通过例子讲解。
2、桥接模式定义

①、Abstraction
抽象化角色:它的主要职责是定义出该角色的行为, 同时保存一个对实现化角色的引用, 该角色一般是抽象类。
②、Implementor
实现化角色:它是接口或者抽象类, 定义角色必需的行为和属性。
③、RefinedAbstraction
修正抽象化角色:它引用实现化角色对抽象化角色进行修正。
④、ConcreteImplementor
具体实现化角色:它实现接口或抽象类定义的方法和属性。
3、桥接模式通用代码实现
实现化类:
public interface Implementor {
void doSomething();
}
具体实现化类:
public class ConcreteImplementor1 implements Implementor{
@Override
public void doSomething() {
// 具体业务逻辑处理
}
}
public class ConcreteImplementor2 implements Implementor{
@Override
public void doSomething() {
// 具体业务逻辑
}
}
这里定义了两个,可能有多个。
抽象化角色:
public abstract class Abstraction {
// 定义对实现化角色的引用
private Implementor implementor;
public Abstraction(Implementor implementor){
this.implementor = implementor;
}
// 自身的行为和属性
public void request(){
this.implementor.doSomething();
}
// 获取实现化角色
public Implementor getImplementor(){
return implementor;
}
}
修正抽象化角色:
public class RefinedAbstraction extends Abstraction{
// 覆写构造函数
public RefinedAbstraction(Implementor implementor){
super(implementor);
}
// 修正父类的行为
@Override
public void request() {
super.request();
}
}
测试:
public class BridgeClient {
public static void main(String[] args) {
// 定义一个实现化角色
Implementor implementor = new ConcreteImplementor1();
// 定义一个抽象化角色
Abstraction abstraction = new RefinedAbstraction(implementor);
// 执行方法
abstraction.request();
}
}
如果我们的实现化角色有很多的子接口, 然后是一堆的子实现。 在构造函数中传递一个明确的实现者, 代码也是很清晰的。
4、桥接模式经典例子—JDBC
我们在刚开始用 JDBC 直连数据库的时候,会有这样一段代码:
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 数据库换成 Oracle 数据库,只需要把第一行代码中的 com.mysql.cj.jdbc.Driver 换成oracle.jdbc.driver.OracleDriver 就可以了。
这种优雅的实现数据库切换方式就是利用了桥接模式。
我们首先看 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 类。
②、执行该类的静态代码,也就是将 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 实现类(比如,com.mysql.cj.jdbc.Driver)注册到 DriverManager 之后,后续所有对 JDBC 接口的调用,都会委派到对具体的 Driver 实现类来执行。而 Driver 实现类都实现了相同的接口(java.sql.Driver ),这也是可以灵活切换 Driver 的原因。

5、桥接模式优点
①、抽象和实现分离
这也是桥梁模式的主要特点, 它完全是为了解决继承的缺点而提出的设计模式。 在该模式下, 实现可以不受抽象的约束, 不用再绑定在一个固定的抽象层次上。
②、优秀的扩充能力
看看我们的例子, 想增加实现? 没问题! 想增加抽象, 也没有问题! 只要对外暴露的接口层允许这样的变化, 我们已经把变化的可能性减到最小。
③、实现细节对客户透明
客户不用关心细节的实现, 它已经由抽象层通过聚合关系完成了封装。
6、桥接模式应用场景
①、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
②、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
③、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
Java设计模式之(六)——桥接模式的更多相关文章
- Java设计模式之《桥接模式》及应用场景
摘要: 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6497919.html 这里摘抄一份他处的概念,你可以不必理会,先看下面得讲解与实例, ...
- 重学 Java 设计模式:实战桥接模式(多支付渠道「微信、支付宝」与多支付模式「刷脸、指纹」场景)
作者:小傅哥 博客:https://bugstack.cn - 编写系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么你的代码那么多ifelse 同类的业务.同样的功能, ...
- Java设计模式学习记录-桥接模式
前言 这次介绍结构型设计模式中的第二种模式,桥接模式. 使用桥接模式的目的就是为了解耦,松散的耦合更利于扩展,但是会增加相应的代码量和设计难度. 桥接模式 桥接模式是为了将抽象化与实现化解耦,让二者可 ...
- 《Java设计模式》之桥接模式
Bridge模式的概念 Bridge 模式是构造型的设计模式之中的一个.Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任.它的主要特点是把抽象(abst ...
- Java设计模式系列之桥接模式
桥接模式(Bridge)的定义 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?这就要使用桥接模式 将抽象部分与它的实现部分分离,使它们都可以独立地 ...
- java设计模式之十桥接模式(Bridge)
桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化.桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时 ...
- java设计模式-----14、桥接模式
Bridge 模式又叫做桥接模式,是构造型的设计模式之一.Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任.它的主要特点是把抽象(abstraction ...
- JAVA设计模式初探之桥接模式
生活中的一个例子: 拿汽车在路上行驶的来说.既有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶.这你会发现,对于交通工具(汽车)有不同的类型,它们所行驶的环境(路)也 ...
- JAVA设计模式之【桥接模式】
桥接模式 蜡笔中颜色和型号之间存在耦合 毛笔中,颜色和型号解耦了 如果软件系统中某个类存在两个独立变化的维度,桥接模式可以将两个维度分离出来 角色 抽象类 扩充抽象类 实现类接口 提供基本操作 抽象类 ...
- 《JAVA设计模式》之桥接模式(Bridge)
在阎宏博士的<JAVA与模式>一书中开头是这样描述桥梁(Bridge)模式的: 桥梁模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式. ...
随机推荐
- 手机淘宝轻店业务 Serverless 研发模式升级实践
一.前言 随着 Serverless 在业界各云平台落地,阿里内部 Serverless 研发平台.各种研发模式也在业务中逐步落地,如火如荼.在此契机下,淘系团队启动了轻店 Serverless 研发 ...
- Rclone使用教程 - 挂载Onedrive和谷歌网盘
1. 介绍 Rclone 是一个用于多个云平台之间同步文件和目录的命令行工具,其支持多种运营商网盘. 官网网址:https://rclone.org 开源地址:https://github.com/n ...
- CF1092F Tree with Maximum Cost(dfs+dp)
果然我已经菜到被\(div3\)的题虐哭了 qwq 首先看到这个题,一个比较显然的想法就是先从1号点开始\(dfs\)一遍,然后通过一些奇怪的方式,再\(dfs\)一遍得到其他点的贡献. 那么具体应该 ...
- Pytorch 实现简单线性回归
Pytorch 实现简单线性回归 问题描述: 使用 pytorch 实现一个简单的线性回归. 受教育年薪与收入数据集 单变量线性回归 单变量线性回归算法(比如,$x$ 代表学历,$f(x)$ 代表收入 ...
- mysql锁场景及排查
1.查询长时间不返回: 在表 t 执行下面的 SQL 语句: mysql> select * from t where id=1; 查询结果长时间不返回. 一般碰到这种情况的话,大概率是表 t ...
- Egg.js学习与实战系列 · Post请求`csrf token`问题
在使用axios请求egg.js封装的post接口时出现missing csrf token 或 invalid csrf token.踩过坑的新手估计不在少数,本篇记录一下解决方法. 问题原因 引用 ...
- Java:阻塞队列
Java:阻塞队列 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 1. 概述 概念 队列 队列就可以想成是一个数组,从一头进入,一头出去,排队买饭 阻塞队列 B ...
- C++ string类型小结
目录 构造函数 string.append() string.assign() string.at() string.back() string.begin() string.capasity() s ...
- configure: error: C preprocessor "arm-linux-gnueabihf-g++" fails sanity check
今天在交叉编译某个编解码库过程中碰到一个configure错误 运行configure的时候设置了一些配置项目 ./configure CC=arm-linux-gnueabihf-gcc CPP=a ...
- 中文NER的那些事儿4. 数据增强在NER的尝试
这一章我们不聊模型来聊聊数据,解决实际问题时90%的时间其实都是在和数据作斗争,于是无标注,弱标注,少标注,半标注对应的各类解决方案可谓是百花齐放.在第二章我们也尝试通过多目标对抗学习的方式引入额外的 ...