桥接(Bridge)模式
桥接模式又称为柄体模式或接口模式。桥接模式的用意就是"将抽象化与实现化解耦,使得二者可以独立变化"。
抽象化:
存在于多个实体中的共同的概念性联系,就是抽象化。作为一个过程,抽象化就是忽略一些信息,从而把不同实体当做同样的实体对待。
实现化:
抽象化给出的具体实现,就是实现化。
脱耦:
耦合是指两个实体的行为的某种强关联。将它们的强关联去掉,就是耦合的解脱或称脱耦。在这里脱耦是将抽象化和实现化的耦合解脱开,或者说是将它们的强关联变为弱关联。继承是强关联。
强关联是指编译时期已经确定的,无法在运行时期动态改变的关联;所谓弱关联就是可以动态地确定并在运行时动态地改变的关联。聚合是弱关联。
将两个角色的继承关系改为聚合关系,就是将它们之间强关联变为弱关联。因此,桥梁模式的脱耦,就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立地变化。
1. 类图与角色

这个系统有两个等级结构:
由抽象化角色和修正抽象化角色组成的抽象化等级结构;
由实现化角色和两个具体实现化角色所组成的实现化等级结构。
涉及的角色有:
抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
实现化(implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。这个接口不一定和抽象化角色定义相同的接口、实现化角色应当只给出低层操作,而抽象化角色应当只给出基于低层操作的更高一层的操作。
具体实现化角色:这个角色给出实现化角色接口的具体实现。
代码如下:
package cn.qlq.bridge;
public abstract class Implementor {
public abstract void operationImpl();
}
package cn.qlq.bridge;
public class ConcreteImplementorA extends Implementor {
@Override
public void operationImpl() {
System.out.println(" ConcreteImplementorA operationImpl ");
}
}
package cn.qlq.bridge;
public class ConcreteImplementorB extends Implementor {
@Override
public void operationImpl() {
System.out.println(" ConcreteImplementorB operationImpl ");
}
}
package cn.qlq.bridge;
public class Abstraction {
private Implementor implementor;
public void operation() {
if (implementor != null) {
implementor.operationImpl();
}
}
public Implementor getImplementor() {
return implementor;
}
public void setImplementor(Implementor implementor) {
this.implementor = implementor;
}
}
package cn.qlq.bridge;
public class RefinedAbstraction extends Abstraction {
@Override
public void operation() {
// 增强逻辑
}
}
2. 桥接模式的例子
一个例子: 手机有多种品牌,又有不同的软件。
(1)不采用桥接模式:

如果需要增加一个MP3音乐播放器。做法就是在手机品牌M和手机品牌N下面都增加一个子类,但是这两个子类的差别可能并不大。
如果需要增加一个品牌L更加复杂,需要增加一个类手机品牌L继承手机品牌,并且还需要两个子类手机品牌L通讯录和手机品牌L游戏并继承手机品牌L。
(2)采用桥接模式的设计如下:

一个抽象"手机品牌"和抽象类"手机软件",不同的品牌和不同的软件分别继承于他们。手机品牌包含有手机软件,但是手机软件并不是品牌的一部分,所以他们之间是聚合关系。
代码如下:
package cn.qlq.bridge.example.plain; import java.util.List; /**
* 抽象手机品牌
*
* @author Administrator
*
*/
public abstract class HandsetBrand { protected List<HandsetSoft> handsetSofts; public HandsetBrand(List<HandsetSoft> handsetSofts) {
super();
this.handsetSofts = handsetSofts;
} abstract void run(); }
package cn.qlq.bridge.example.plain; import java.util.List; /**
* 手机品牌M
*
* @author Administrator
*
*/
public class HandsetBrandM extends HandsetBrand { public HandsetBrandM(List<HandsetSoft> handsetSofts) {
super(handsetSofts);
} @Override
void run() {
for (HandsetSoft handsetSoft : handsetSofts) {
handsetSoft.run();
}
} }
package cn.qlq.bridge.example.plain; import java.util.List; /**
* 手机品牌N
*
* @author Administrator
*
*/
public class HandsetBrandN extends HandsetBrand { public HandsetBrandN(List<HandsetSoft> handsetSofts) {
super(handsetSofts);
} @Override
void run() {
for (HandsetSoft handsetSoft : handsetSofts) {
handsetSoft.run();
}
} }
package cn.qlq.bridge.example.plain; /**
* 手机软件
*
* @author Administrator
*
*/
public abstract class HandsetSoft { abstract void run();
}
package cn.qlq.bridge.example.plain; /**
* 手机游戏
*
* @author Administrator
*
*/
public class HandsetGame extends HandsetSoft { @Override
void run() {
System.out.println("手机游戏");
} }
package cn.qlq.bridge.example.plain;
public class HandsetAddressList extends HandsetSoft {
@Override
void run() {
System.out.println("手机通讯录");
}
}
这时候如果增加一个功能,只需要增加一个类:
package cn.qlq.bridge.example.plain;
public class HandsetMP3 extends HandsetSoft {
@Override
void run() {
System.out.println("mp3");
}
}
如果需要增加一个新品牌L,也是增加一个类:
package cn.qlq.bridge.example.plain; import java.util.List; /**
* 手机品牌L
*
* @author Administrator
*
*/
public class HandsetBrandL extends HandsetBrand { public HandsetBrandL(List<HandsetSoft> handsetSofts) {
super(handsetSofts);
} @Override
void run() {
for (HandsetSoft handsetSoft : handsetSofts) {
handsetSoft.run();
}
} }
3. 桥接模式适用场景
如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。
设计要求实现化角色的任何改变不影响客户端,或者实现化角色的改变对客户端是完全透明的。
一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态解耦。
虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
总结:
上面的设计也符合开闭原则。相比聚合,继承更容易造成不必要的麻烦。在使用继承时,一定要在"is - a" 关系的时候再考虑使用。
由于上面的两个抽象类之间有一个聚合的关系箭头,有一条聚合线,这么理解更容易记住 桥接 模式。
桥接(Bridge)模式的更多相关文章
- 设计模式初探-桥接(Bridge)模式
桥接(Bridge)模式,又称Handle/Body模式,属于对象结构型模式.用于将抽象部分与它的实现部分分离,使它们都可以独立地变化.比如常见的电脑窗口界面,不同的操作系统其窗口界面绘制的原理肯定不 ...
- Java 实现桥接(Bridge)模式
类图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamp3d21scDQ1Ng==/font/5a6L5L2T/fontsize/400/fill/I0 ...
- 设计模式C++描述----09.桥接(Bridge)模式
一. 举例 N年前: 计算机最先出来时,软件和硬件是一绑在一起的,比如IBM出了一台电脑,上面有一个定制的系统,假如叫 IBM_Win,这个IBM_Win系统当然不能在HP电脑上运行,同样HP出的HP ...
- Java设计模式---桥接Bridge模式
参考于 : 大话设计模式 马士兵设计模式视频 写在开头: 桥接模式主要用于一件事物分成了两个维度,进行排列组合,比如礼物,可以分成优雅的礼物(抽象),花(具体),排列组合优雅的花! 1.为什么使用桥接 ...
- 设计模式--桥接(Bridge)模式
1.概述: 桥接模式:把抽象和行为分离开来,中间需要某个介质来连接抽象化和行为化.此模式的概述听起来非常像适配器模式,不要搞混了,虽然都是借用中间介质,但意义不同.最典型的桥接模式就是:JDBC.通过 ...
- 漫谈设计模式(三):桥接(Bridge)模式 —— 将类功能、结构两层次分离
1.前言 类主要有两个层次,一个是功能层次,另一个是实现层次. 功能层次,一般应用于当前类不能满足多样化的业务需求,让子类去继承(具体)父类,添加加一些父类中没有的功能(一般是增加新的方法),这就属于 ...
- 【设计模式】Bridge模式(桥接模式)
最近的一次面试中,被问到桥接模式,以前呢并没有很仔细的研究过这个设计模式,借此机会剖析一下. 先给出自己对这个模式理解后的源码: interface A{ void methodA(); } inte ...
- Bridge(桥接)模式
1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...
- 接口型模式(二)Bridge(桥接)模式
目的: 将抽象与抽象方法的实现相分离,使得它们可以独自变化.常用于驱动程序中,使得顶层逻辑不受驱动底层改变的影响,如数据库的变化. 关键词:Bridge, 抽象与实现分离,驱动程序 必要性:从一般抽象 ...
随机推荐
- nginx之旅(第一篇):nginx下载安装、nginx启动与关闭、nginx配置文件详解、nginx默认网站
一.nginx下载安装 版本nginx 1.15.5 系统环境centos7.5(本机ip192.168.199.228) 关闭selinux 和防火墙firewall 1.下载 wget http: ...
- 【数据库】数据库入门(四): SQL查询 - SELETE的进阶使用
集合操作常用的集合操作主要有三种:UNION(联合集).INTERSECT(交叉集).EXCEPT(求差集).以上三种集合的操作都是直接作用在两个或者多个 SQL 查询语句之间,将所有的元组按照特定的 ...
- Python 实现两个矩形重合面积
计算两个矩形的重合面积 import math x1, y1, x2, y2 = input().split(" ") x1, y1, x2, y2=int(x1), int(y1 ...
- 1. 观察者模式总结(C++)
1. 介绍 观察者模式:定义了一种"一对多"的依赖关系,让多个观察者对象同时监听一个对象的改变,即当该对象的状态发现改变时,会通知所有它依赖的观察者对象.观察者模式属于行为模式. ...
- python参数传递
1.形式参数:在定义函数时,函数名后面括号中的参数为“形式参数”,也称形参 2.实际参数:在调用一个函数时,函数名后面括号种的参数为“实际参数”,也就是将函数的调用者提供给函数的参数称为实际参数,也称 ...
- mdk编译器学习笔记(1)——序
这两天,学习了keil-mdk编译器的特性,这基本上独立于c语言语法,平时基本上都在强调c语言的学习,但是编译器的学习我们也要注重,类似于gcc一样,不也有很多网上的资料,讲述gcc的特性和用法吗.作 ...
- CSRF跨域伪造请求
后端生成一个加密token,将其设置在cookie当中,专用于表单数据提交时的验证,并且前端在表单中多增加一个隐藏字段,每当用户提交表单数据时(post请求),将这个隐藏字段一并提交,后端再对表单中的 ...
- Anaconda3(0)环境基本使用
https://blog.csdn.net/u012005313/article/details/82347817 主要内容: 查看环境列表 创建新的 Python 环境 激活/停止 Python 环 ...
- 31 树莓派外接Oled屏幕
http://shumeipai.nxez.com/2017/09/13/solve-the-raspberry-pi-drive-oled-problem.html
- Pandas | 27 注意事项&窍门
警告和疑难意味着一个看不见的问题.在使用Pandas过程中,需要特别注意的地方. 与Pandas一起使用If/Truth语句 当尝试将某些东西转换成布尔值时,Pandas遵循了一个错误的惯例. 这种情 ...