设计模式-桥接模式

迭代根系
• 阅读 3066

桥接模式

定义

抽象部分和具体实现部分分离

  • 让他们可以独立的变化
  • 通过组合的方式建立两个类之间的关系而不是继承
结构型模式

生活中的场景

连接了两个维度的东西

网络连接

桥接模式

虚拟网卡和物理网卡连在一起

通用的写法

设计模式-桥接模式

里面有几个关键角色

Abstraction——抽象化角色

​ 它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类。

Implementor——实现化角色

它是接口或者抽象类,定义角色必需的行为和属性。

RefinedAbstraction——修正抽象化角色

它引用实现化角色对抽象化角色进行修正。

ConcreteImplementor——具体实现化角色

它实现接口或抽象类定义的方法和属性。

public class RefinedAbstraction extends Abstraction {
  public RefinedAbstraction(IImplementor implementor) {
    super(implementor);
  }

  @Override
  public void operation() {
    super.operation();
    System.out.println("refined operation");
  }
}
public class Test {

  public static void main(String[] args) { 
    //定义一个实现化角色
    Implementor imp = new ConcreteImplementor1();
    //定义一个抽象化角色
    Abstraction abs = new RefinedAbstraction(imp); 
    //执行行文
    abs.request(); 
  }

}
}

测试用例

public class Test {
  public static void main(String[] args) {
    // 来一个实现化角色
    IImplementor imp = new ConcreteImplementorA();
    // 来一个抽象化角色,聚合实现
    Abstraction abs = new RefinedAbstraction(imp);
    // 执行操作
    abs.operation();
  }
}

​ 各位可能要问,为什么要增加一个构造函数?答案是为了提醒子类,你必须做这项工作,指定实现者,特别是已经明确了实现者,则尽量清晰明确地定义出来。

案例

抽象工厂的问题

以前我们在写抽象工厂模式的时候是这样来做的

设计模式-桥接模式

从上图可以看到,抽象工厂是用来帮我们创建不同的课程有相同的共性的问题

例如Java课程和python课程都需要记笔记和录制视频,所以我们可以通过抽象工厂CourseFactory来创建,但是这种方式是通过继承来做的,并且我们的产品和工厂都绑的太死了,所以我们可以通过桥梁模式来帮我们解绑,用组合和聚合来代理继承。

桥接模式来松绑

设计模式-桥接模式

可以看到通过AbstractCourse给笔记和视频搭建了一个桥梁

public class AbstractCourse implements ICourse {
  private INote note;
  private IVideo video;

  public void setNote(INote note) {
    this.note = note;
  }

  public void setVideo(IVideo video) {
    this.video = video;
  }

  @Override
  public String toString() {
    return "AbstractCourse{" +
      "note=" + note +
      ", video=" + video +
      '}';
  }
}

这样我们就通过桥梁AbstractCourse来帮我们建立起了笔记和视频的联系

消息

设计模式-桥接模式

我们可以通过桥接模式来构建消息类型和发送消息的关系

设计模式-桥接模式

public abstract class AbastractMessage {
  private IMessage message;

  public AbastractMessage(IMessage message) {
    this.message = message;
  }

  void sendMessage(String message, String toUser) {
    this.message.send(message, toUser);
  }
}

使用如下

public class Test {
  public static void main(String[] args) {
    IMessage message = new SmsMessage();
    AbastractMessage abastractMessage = new NomalMessage(message);
    abastractMessage.sendMessage("加班申请","王总");

    message = new EmailMessage();
    abastractMessage = new UrgencyMessage(message);
    abastractMessage.sendMessage("加班申请","王总");
  }
}
感觉桥接模式和装饰者有点像

源码中的桥接模式

JDBC

设计模式-桥接模式

初始化

当我们执行如下代码的时候

/**
  * JDBC规定了这些步骤,但是没有具体实现。<br>
  * 这些具体实现跟抽象步骤怎么衔接起来呢?通过DriverManager来桥接<br/>
  */
try {
  //1.加载驱动  ---> 建立桥
  Class.forName("com.mysql.jdbc.Driver");  //反射机制加载驱动类,执行静态块代码,调用Driver的构造方法<br>
  // 2.获取连接Connection
  //主机:端口号/数据库名  --> 前面建立桥了 这里就用
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/ds0", "admin", "admin");
  // 3.得到执行sql语句的对象Statement
  Statement stmt = conn.createStatement();
  // 4.执行sql语句,并返回结果
  ResultSet rs = stmt.executeQuery("select *from table");
}catch (Exception e){
  e.printStackTrace();
}
}

会执行对应的静态代码块

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!");
        }
    }
}

java.sql.DriverManager#registerDriver(java.sql.Driver, java.sql.DriverAction)

private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();

public static synchronized void registerDriver(java.sql.Driver driver,
                                               DriverAction da)
  throws SQLException {

  /* Register the driver if it has not already been added to our list */
  if(driver != null) {
    registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
  } else {
    // This is for compatibility with the original DriverManager
    throw new NullPointerException();
  }

  println("registerDriver: " + driver);

}

可以看到帮我们把对应的驱动对象包装了一层变成了DriverInfo,并且存放起来了

获取连接

java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties, java.lang.Class<?>)

for(DriverInfo aDriver : registeredDrivers) {
  // If the caller does not have permission to load the driver then
  // skip it.
  if(isDriverAllowed(aDriver.driver, callerCL)) {
    try {
      println("    trying " + aDriver.driver.getClass().getName());
      Connection con = aDriver.driver.connect(url, info);
      if (con != null) {
        // Success!
        println("getConnection returning " + aDriver.driver.getClass().getName());
        return (con);
      }
    } catch (SQLException ex) {
      if (reason == null) {
        reason = ex;
      }
    }

  } else {
    println("    skipping: " + aDriver.getClass().getName());
  }
}

可以看到获取连接的时候,从之前已经存起来的驱动里面来获取连接,并且返回出去

通过一个集合帮我们构建了一个桥梁

总结

适用场景

  • 抽象和实现分离

    • 能够帮我们解决继承的问题

      • 单继承
      • 暴露过多属性给子类
      • 或者因为多继承导致类的个数剧增
      • 无法喜更细化场景
  • 优秀的扩展能力

    • 我们桥梁都是面向抽象的
    • 增加桥也是能够快速增加的
  • 一个类存在两个或者多个独立变化的维度

    • 这两个维度都需要独立进行扩展
  • 接口或者抽象类不稳定的场景

    • 如果通过继承,修改的会非常多
  • 重用性要求高的场景

    • 继承会导致受到父类的限制,粒度不会太细

优点

  • 分离了抽象部分和具体实现部分

    • 我们通过桥梁可以解决继承的缺点
  • 提高了系统的扩展
  • 符合开闭原则
  • 符合合成复用原则

缺点

  • 增加了系统的理解和设计难度
  • 需要正确的识别系统中两个独立变化的维度

和其他设计模式的关联

桥接模式更加注重形式

桥接模式更加注重连接,适配器模式更加注重适配

注意

​ 不能说继承不好,它非常好,但是有缺点,我们可以扬长避短,对 于比较明确不发生变化的,则通过继承来完成;若不能确定是否会发生 变化的,那就认为是会发生变化,则通过桥梁模式来解决,这才是一个完美的世界。

问题

想一下桥接模式怎么不使用继承的情况下怎么把两个维度结合起来的呢,可以举个例子或者对于上述案例加以说明也行
  • 在java当中除了继承就是组合和聚合了

    • 如果通过继承

      • 那么子类会持有很多父类的东西,并且很容易重写父类的方法,违背里氏替换原则
    • 如果通过组合和聚合

      • 子类想要拥有方法很简单,桥梁打过去,获得这个方法就行了
      • 例如

      设计模式-桥接模式

      我们集团组要功能是赚钱,赚钱需要先生产然后销售crop当前是抽象类具体的生产产品,和销售交给旗下的子公司HouseCrop卖房子的和IpodCorp卖Ipod的来卖钱

    • public class Client {
        public static void main(String[] args) {
          System.out.println("-------房地产公司是这样运行的------");
          //先找到我的公司
          HouseCorp houseCorp = new HouseCorp();
          //看我怎么挣钱
          houseCorp.makeMoney();
          System.out.println("\n");
          System.out.println("-------服装公司是这样运行的-------");
      
          ClothesCorp clothesCorp = new ClothesCorp();
          clothesCorp.makeMoney();
      
        }
      }

      很明显现在有一个问题,我们的工厂和具体的产品绑的太死了,比如说但是我们不想用抽象工厂那么可以通过桥接模式来解决,用组合来把他们构建起来

      设计模式-桥接模式

      可以让山寨的工厂也能生产房子和ipod其实就是通过桥梁模式让我们的具体公司能够和产品关联起来

我们平常写JDBC代码的时候有没有去琢磨一下这句代码DriverManager.getConnection("jdbc:mysql://localhost:3306/ds0", "admin", "admin");是怎么拿到mysqlConnection。

设计模式-桥接模式

我的笔记仓库地址gitee 快来给我点个Star吧
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
4年前
java 设计模式之模板模式
什么是模板模式模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。模板方法模式的结构抽象类(AbstractClass):
Wesley13 Wesley13
4年前
VirtualBox网络接入模式
VirtualBox的提供了四种网络接入模式,它们分别是:1、NAT  网络地址转换模式(NAT,NetworkAddressTranslation)2、BridgedAdapter  桥接模式3、Internal  内部网络模式4、HostonlyAdapter 主机模式下面我们分别对这四种网络模
Wesley13 Wesley13
4年前
VirtualBox网络NAT模式的端口映射设置
VirtualBox的提供了四种网络接入模式,它们分别是:1、NAT网络地址转换模式(NAT,NetworkAddressTranslation)2、BridgedAdapter桥接模式3、Internal内部网络模式4、HostonlyAdapter主机模式其中NAT模式是最简单的实现虚拟机上网的方式,可以认为
Wesley13 Wesley13
4年前
Java描述设计模式(04):抽象工厂模式
一、抽象工厂模式1、生活场景汽车生产根据用户选择的汽车类型,指定不同的工厂进行生产,选择红旗轿车,就要使用中国工厂,选择奥迪轿车,就要使用德国工厂。2、抽象工厂模式1.抽象工厂模式:定义了一个interface用于创建相关对象或相互依赖的对象,而无需指明具体的类;2.抽象工厂模式可以
Wesley13 Wesley13
4年前
Java设计模式
一、策略模式(让算法与对象独立)    策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。!(http://static.oschina.net/uploads/space/2016/1108/180244_oYm8_1789589.png)二、观察者模式(让你的对象知悉现状) 
Stella981 Stella981
4年前
CentOS7.3+MySQL5.7+Apache2.4+PHP7.1+phpMyAdmin4.7+JDK1.8+SVN1.6+Jenkins2.1环境搭建
CentOS7.3MySQL5.7Apache2.4PHP7.1phpMyAdmin4.7JDK1.8SVN1.6Jenkins2.1环境搭建1、安装CentOS7.3虚拟机安装说明:在创建虚拟机时,选择桥接模式1)进入安装界面后,选择Installorupgradeanexistingsystem选项2)选择En
Wesley13 Wesley13
4年前
Java中23种设计模式详解
Java中23种设计模式1\.设计模式31.1创建型模式41.1.1工厂方法41.1.2抽象工厂61.1.3建造者模式101.1.4单态模式131.1.5原型模式151.2结构型模式171.2.1适配器模式171.2.2桥接模式191.2.3组合
Wesley13 Wesley13
4年前
Java Design Patterns
java的设计模式大体上分为三大类:创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模
Wesley13 Wesley13
4年前
23种设计模式(面向对象语言)
一、设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其他关联对象的创建、组合和表示方式。所有的创建型模式都有两个主要功能:  1.将系统所使用的具体类的信息封装起来  2.隐藏
Wesley13 Wesley13
4年前
Java 设计模式系列(十三)模板方法
Java设计模式系列(十三)模板方法模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。一、模板方法的结构
设计模式-单例模式概述 | 京东云技术团队
我们常把23种经典的设计模式分为三类:创建型、结构型、行为型,其中创建型设计模式主要解决“对象的创建”问题,将创建和使用代码解耦,结构型设计模式主要解决“类或对象的组合或组装”问题,将不同功能代码解耦,行为型设计模式主要解决“类或对象之间的交互”问题,将不
迭代根系
迭代根系
Lv1
鞭个马儿归去也,心急马行迟。
文章
4
粉丝
0
获赞
0