003-结构型-05-桥接模式(Bridge)
一、概述
将抽象部分与它的具体实现部分分离。使它们都可以独立地变化。通过组合的方式建立两个类之间联系,而不是继承。
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)的更多相关文章
- 【设计模式】结构型04桥接模式(Bridge Pattern)
学习地址:http://www.runoob.com/design-pattern/bridge-pattern.html 桥接模式(Bridge Pattern) 桥接模式(Bridge patte ...
- 【设计模式】结构型05组合模式(Composite Pattern)
组合模式(Composite Pattern) 意图:将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 主要解决:它在我们 ...
- 【设计模式】桥接模式 Bridge Pattern
开篇还是引用吕振宇老师的那篇经典的文章<设计模式随笔-蜡笔与毛笔的故事>.这个真是太经典了,没有比这个例子能更好的阐明桥接模式了,这里我就直接盗来用了. 现在市面上卖的蜡笔很多,各种型号, ...
- python 设计模式之桥接模式 Bridge Pattern
#写在前面 前面写了那么设计模式了,有没有觉得有些模式之间很类似,甚至感觉作用重叠了,模式并不是完全隔离和独立的,有的模式内部其实用到了其他模式的技术,但是又有自己的创新点,如果一味地认为每个模式都是 ...
- 桥接模式(Bridge、Implementor)(具体不同平台日志记录,抽象与实现分离)
桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化.它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式 ...
- 桥接模式(Bridge Pattern)
1,定义 桥接模式(Bridge Pattern),也称为桥梁模式,其用意是将抽象化与实现化脱耦,使得两者可以独立的变化,它可以使软件系统沿着多个方向进行变化,而又不引入额外的复杂 ...
- c#桥接模式(bridge结构模式)
桥接模式(bridge结构模式)c#简单例子 在前面的玩家中每增加一个行为,就必须在每个玩家中都增加,通过桥接模式将行为提取出来了,减少变化 ? 1 2 3 4 5 6 7 8 9 10 11 12 ...
- 【结构型】Flyweight模式
享元模式的主要目的.意图是为对象的大量使用提供一种共享机制.该模式的思想重在复用.共享复用.像文字.列表中的格子等这类多数都是需要考虑复用技术,否则必将大量耗费内存空间而使资源以及性能等大量耗费.该模 ...
- 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern)
原文:乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) 作者:webabcd 介绍 ...
- 桥接模式-Bridge(Java实现)
桥接模式-Bridge 桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦, 将"类的功能层次结构" 与 "类的实 ...
随机推荐
- 《你说对就队》第八次团队作业:Alpha冲刺
<你说对就队>第八次团队作业:Alpha冲刺 项目 内容 这个作业属于哪个课程 [教师博客主页链接] 这个作业的要求在哪里 [作业链接地址] 团队名称 <你说对就队> 作业学习 ...
- Linux命令基础3-cd命令
cd 到带空格的文件夹 [root@cctg-sjc16-grafana ccatgbld]# cd 'my test' [root@cctg-sjc16-grafana my test]# cd . ...
- LightOJ-1275-Internet Service Providers(数学)
链接: https://vjudge.net/problem/LightOJ-1275 题意: A group of N Internet Service Provider companies (IS ...
- nginx优化、负载均衡、rewrite
nginx优化 # 普通用户启动 (useradd nginx -s /sbin/nologin -M) user nginx; # 配置nginx worker进程个数 #worker_proces ...
- Oracle substr() 字符截取函数
1.substr函数格式 (俗称:字符截取函数) 格式1: substr(string string, int a, int b); 格式2:substr(string string, int a ...
- editplus 支持lua语言语法高亮显示
找到自己的安装目录 建一个这个名字的文件 里面写上 #TITLE=LUA ; LUA syntax file written by ES-Computing. ; This file is requi ...
- 2017.10.2 国庆清北 D2T2 树上抢男主
/* 我只看懂了求LCA */ #include<iostream> #include<cstring> #include<cstdio> #include< ...
- Matlab中的变量名
在Matlab中使用save和load命令时,可能会出现变量名出错的问题. 如: save('A1.mat', 'A1'); load('A1.mat', 'A1'); 如果程序中还有名为a1的变量名 ...
- git的实际工作经验总结
分支工作的一个较佳的实践, 即git工作的最佳实践 从最初的svn到后来的git,上来给我的感觉就是git更方便, 可以在本地进行版本的提交,回退. 后来对hash有所了解, 知道了git的每个版本其 ...
- 让img图片像背景一样显示
如何让图片像背景一样显示呢? 这里需要用到object-fit属性 MDN地址:https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fit ...