一、概述

  将抽象部分与它的具体实现部分分离。使它们都可以独立地变化。通过组合的方式建立两个类之间联系,而不是继承。

  Bridge 模式又叫做桥接模式,是构造型的设计模式之一。Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。

  它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。

  常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。

1.1、适用场景

  如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。

  抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。

  一个类存在两个(或多个)独立变化的维度。且这两个(或多个)维度都需要独立进行扩展

  虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。

  不希望使用继承,或因为多层继承导致系统类的个数剧增

1.2、优缺点

优点:

  • 分离抽象部分及其具体实现部分
  • 提高了系统的可扩展性
  • 符合开闭原则,可动态的切换实现
  • 符合合成复用原则,实现细节对客户端透明,可以对用户隐藏实现细节

缺点:

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

对比其他模式

桥接模式和组合模式

  • 组合模式强调的是部分和整体间的组合,桥接模式强调的是平行级别上,不同类的组合

桥接模式和适配器模式

  • 适配器模式改变已有的接口,桥接模式分离抽象和具体

1.3、类图角色及其职责

  

  桥接模式的角色和职责

  1、Client:Bridge模式的使用者

  2、Abstraction(Car)

      (1)抽象类接口(接口或抽象类)

  (2)维护对行为实现(Implementor)的引用

  3、Refined Abstraction(Bus、Suv):Abstraction子类

  4、Implementor(Engine): 行为实现类接口 (Abstraction接口定义了基于Implementor接口的更高层次的操作)

  5、ConcreteImplementor(OilEngine、ElectricityEngine):Implementor子类

抽象画

  

接口定义

public interface Sourceable {
public void method();
}

分别定义两个实现类:

public class SourceSub1 implements Sourceable {  

    @Override
public void method() {
System.out.println("this is the first sub!");
}
}
public class SourceSub2 implements Sourceable {  

    @Override
public void method() {
System.out.println("this is the second sub!");
}
}

定义一个桥,持有Sourceable的一个实例:

public abstract class Bridge {
private Sourceable source; public void method(){
source.method();
} public Sourceable getSource() {
return source;
} public void setSource(Sourceable source) {
this.source = source;
}
}
public class MyBridge extends Bridge {
public void method(){
getSource().method();
}
}

测试

public class BridgeTest {  

    public static void main(String[] args) {  

        Bridge bridge = new MyBridge();  

        /*调用第一个对象*/
Sourceable source1 = new SourceSub1();
bridge.setSource(source1);
bridge.method(); /*调用第二个对象*/
Sourceable source2 = new SourceSub2();
bridge.setSource(source2);
bridge.method();
}
}

1.4、演进过程

  举个例子,我们都知道,汽车有不同的发动机,有油的,有电的,还有用天然气的

  我们先举两个不采用桥接模式的例子,通过对比,来看出桥接模式的优势

示例一、

  项目代码:https://github.com/bjlhx15/patterns.git 中的patterns-base 中 structure/bridge/process01

  基础接口

/*
* 汽车
*/
public interface Car {
//安装引擎
void installEngine();
}

  先新建以下基础结构  

  

  运行测试

    @Test
public void test() {
Car car = new OilBus();
car.installEngine();
}

  查看类图结构  

  

  可以看到,一种车每增加一种发动机就要增加一个子类,到了后期,子类会越来越多,越来越庞大。这种方法不推荐使用。

示例二、

  项目代码:https://github.com/bjlhx15/patterns.git 中的patterns-base 中 structure/bridge/process02

把所有的发动机都定义到Car接口中,每种车实现一次就好了

/*
* 汽车
*/
public interface Car {
//安装燃油引擎
public void installOilEngine();
//安装电动引擎
public void installElectricityEngine();
}

测试

    @Test
public void test(){
Car bus = new Bus();
Car suv = new Suv(); bus.installOilEngine();
bus.installElectricityEngine(); suv.installOilEngine();
suv.installElectricityEngine();
}

  UML图

  

  这种方式就没有那么多子类了,每种车只有一个实现类,但是这种方法不符合我们的开放封闭原则,每增加一种发动机,就要修改Car接口,并修改所有实现类。这种方法肯定也是不推荐的。

示例三、桥接模式

项目代码:https://github.com/bjlhx15/patterns.git 中的patterns-base 中 structure/bridge/impl

创建发动机接口

/*
* 发动机
*/
public interface Engine {
public void installEngine();
}

以及车抽象类

/*
* 汽车
*/
public abstract class Car {
private Engine engine; public Car(Engine engine){
this.engine = engine;
} //安装发动机
public abstract void installEngine(); public Engine getEngine() {
return engine;
} public void setEngine(Engine engine) {
this.engine = engine;
}
}

基础类

  

UML类图

  

  测试

    @Test
public void getEngine() {
Engine oilEngine = new OilEngine();
Engine electricityEngine = new ElectricityEngine(); Car oilBus = new Bus(oilEngine);
Car electricityBus = new Bus(electricityEngine); Car oilSuv = new Suv(oilEngine);
Car electricitySuv = new Suv(electricityEngine); oilBus.installEngine();
electricityBus.installEngine(); oilSuv.installEngine();
electricitySuv.installEngine();
}

二、扩展

2.1、JDK中实现的桥接模式

1、 java.sql.Driver、java.sql.DriverManager与java.sql.DriverInfo
mysql的Driver、oracle的Driver就是桥接模式的实现部分。

2、DriverManager与DriverInfo(也就是Driver)实现了桥接模式

003-结构型-05-桥接模式(Bridge)的更多相关文章

  1. 【设计模式】结构型04桥接模式(Bridge Pattern)

    学习地址:http://www.runoob.com/design-pattern/bridge-pattern.html 桥接模式(Bridge Pattern) 桥接模式(Bridge patte ...

  2. 【设计模式】结构型05组合模式(Composite Pattern)

    组合模式(Composite Pattern) 意图:将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 主要解决:它在我们 ...

  3. 【设计模式】桥接模式 Bridge Pattern

    开篇还是引用吕振宇老师的那篇经典的文章<设计模式随笔-蜡笔与毛笔的故事>.这个真是太经典了,没有比这个例子能更好的阐明桥接模式了,这里我就直接盗来用了. 现在市面上卖的蜡笔很多,各种型号, ...

  4. python 设计模式之桥接模式 Bridge Pattern

    #写在前面 前面写了那么设计模式了,有没有觉得有些模式之间很类似,甚至感觉作用重叠了,模式并不是完全隔离和独立的,有的模式内部其实用到了其他模式的技术,但是又有自己的创新点,如果一味地认为每个模式都是 ...

  5. 桥接模式(Bridge、Implementor)(具体不同平台日志记录,抽象与实现分离)

    桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化.它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式 ...

  6. 桥接模式(Bridge Pattern)

    1,定义           桥接模式(Bridge Pattern),也称为桥梁模式,其用意是将抽象化与实现化脱耦,使得两者可以独立的变化,它可以使软件系统沿着多个方向进行变化,而又不引入额外的复杂 ...

  7. c#桥接模式(bridge结构模式)

    桥接模式(bridge结构模式)c#简单例子 在前面的玩家中每增加一个行为,就必须在每个玩家中都增加,通过桥接模式将行为提取出来了,减少变化 ? 1 2 3 4 5 6 7 8 9 10 11 12 ...

  8. 【结构型】Flyweight模式

    享元模式的主要目的.意图是为对象的大量使用提供一种共享机制.该模式的思想重在复用.共享复用.像文字.列表中的格子等这类多数都是需要考虑复用技术,否则必将大量耗费内存空间而使资源以及性能等大量耗费.该模 ...

  9. 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern)

    原文:乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) 作者:webabcd 介绍 ...

  10. 桥接模式-Bridge(Java实现)

    桥接模式-Bridge 桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦, 将"类的功能层次结构" 与 "类的实 ...

随机推荐

  1. Spring -13 -Spring 中常用注解总结

    1.@Component 创建类对象,相当于配置<bean/> 2.@Service 与@Component 功能相同. 2.1都写在ServiceImpl 类上. 3.@Reposito ...

  2. LG4723 【模板】常系数线性递推

    P4723 [模板]常系数齐次线性递推 题目描述 求一个满足$k$阶齐次线性递推数列${a_i}$的第$n$项. 即:$a_n=\sum\limits_{i=1}^{k}f_i \times a_{n ...

  3. Java - 框架之 SpringBoot 攻略day01

          Spring-Boot 攻略 day01 spring-boot   一. 基本配置加运行   1. 导入配置文件(pom.xml 文件中)   <parent> <gr ...

  4. S1_搭建分布式OpenStack集群_02 虚拟机环境配置

    一.配置主机名及hosts和防火墙(只演示一台,其他机器配置方式一样)vim /etc/hosts  加入    10.10.11.11 controller10.10.11.12 compute11 ...

  5. Linux中三种SCSI target的介绍之LIO

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/scaleqiao/article/deta ...

  6. TPS与QPS,以及GMV

    TPS是指每秒处理事务的个数,处理的载体可以是单台服务器,也可以是一个服务器集群. 例如:下单接口,一秒内,下单完成次数为1000,则下单接口总 tps = 1000,共有10台服务器提供下单服务,单 ...

  7. SDOI R2 咕咕记

    Day 0 路上堵车,\(5\)点才到宾馆 \(BCT\)为什么在山上啊!!!! 试机的时候敲了一下多项式求逆的板子 回到宾馆订了\(KFC\)的外卖 Day 1 爬山的时候跟\(asuldb\)说 ...

  8. php-fpm 参数调优

    php-fpm 进程池优化方法 php-fpm进程池开启进程有两种方式,一种是static,直接开启指定数量的php-fpm进程,不再增加或者减少:另一种则是dynamic,开始时开启一定数量的php ...

  9. nodejs新工具-cypress和testcofe的崛起

    今天咨询一个自动化 工具问题,偶然间有人提起了这个可能以后会很火的工具,在此找到一篇很好的参考文章 记录并为以后做准备 cypress和testcofe https://www.jianshu.com ...

  10. "中国东信杯"广西大学第二届程序设计竞赛 - H - Antinomy与伊尔美格

    题意:给一个有向图,n个点m条边,每个点有点权xi.规定从u点出发,到指定的k个点之一结束,可以多次经过同一个点和同一条边,求路径上点权和的最大值. 题解:直接缩点变成DAG,然后dp的时候并不是直接 ...