桥接模式又称为柄体模式或接口模式。桥接模式的用意就是"将抽象化与实现化解耦,使得二者可以独立变化"。

抽象化:

  存在于多个实体中的共同的概念性联系,就是抽象化。作为一个过程,抽象化就是忽略一些信息,从而把不同实体当做同样的实体对待。

实现化:

  抽象化给出的具体实现,就是实现化。

脱耦:

  耦合是指两个实体的行为的某种强关联。将它们的强关联去掉,就是耦合的解脱或称脱耦。在这里脱耦是将抽象化和实现化的耦合解脱开,或者说是将它们的强关联变为弱关联。继承是强关联。

  强关联是指编译时期已经确定的,无法在运行时期动态改变的关联;所谓弱关联就是可以动态地确定并在运行时动态地改变的关联。聚合是弱关联。

  将两个角色的继承关系改为聚合关系,就是将它们之间强关联变为弱关联。因此,桥梁模式的脱耦,就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立地变化。

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)模式的更多相关文章

  1. 设计模式初探-桥接(Bridge)模式

    桥接(Bridge)模式,又称Handle/Body模式,属于对象结构型模式.用于将抽象部分与它的实现部分分离,使它们都可以独立地变化.比如常见的电脑窗口界面,不同的操作系统其窗口界面绘制的原理肯定不 ...

  2. Java 实现桥接(Bridge)模式

    类图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamp3d21scDQ1Ng==/font/5a6L5L2T/fontsize/400/fill/I0 ...

  3. 设计模式C++描述----09.桥接(Bridge)模式

    一. 举例 N年前: 计算机最先出来时,软件和硬件是一绑在一起的,比如IBM出了一台电脑,上面有一个定制的系统,假如叫 IBM_Win,这个IBM_Win系统当然不能在HP电脑上运行,同样HP出的HP ...

  4. Java设计模式---桥接Bridge模式

    参考于 : 大话设计模式 马士兵设计模式视频 写在开头: 桥接模式主要用于一件事物分成了两个维度,进行排列组合,比如礼物,可以分成优雅的礼物(抽象),花(具体),排列组合优雅的花! 1.为什么使用桥接 ...

  5. 设计模式--桥接(Bridge)模式

    1.概述: 桥接模式:把抽象和行为分离开来,中间需要某个介质来连接抽象化和行为化.此模式的概述听起来非常像适配器模式,不要搞混了,虽然都是借用中间介质,但意义不同.最典型的桥接模式就是:JDBC.通过 ...

  6. 漫谈设计模式(三):桥接(Bridge)模式 —— 将类功能、结构两层次分离

    1.前言 类主要有两个层次,一个是功能层次,另一个是实现层次. 功能层次,一般应用于当前类不能满足多样化的业务需求,让子类去继承(具体)父类,添加加一些父类中没有的功能(一般是增加新的方法),这就属于 ...

  7. 【设计模式】Bridge模式(桥接模式)

    最近的一次面试中,被问到桥接模式,以前呢并没有很仔细的研究过这个设计模式,借此机会剖析一下. 先给出自己对这个模式理解后的源码: interface A{ void methodA(); } inte ...

  8. Bridge(桥接)模式

    1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...

  9. 接口型模式(二)Bridge(桥接)模式

    目的: 将抽象与抽象方法的实现相分离,使得它们可以独自变化.常用于驱动程序中,使得顶层逻辑不受驱动底层改变的影响,如数据库的变化. 关键词:Bridge, 抽象与实现分离,驱动程序 必要性:从一般抽象 ...

随机推荐

  1. Spring Cloud入门

    Spring Cloud为开发者开发分布式应用提供了便捷工具(包括配置管理.服务发现.断路器.智能路由.微服务代理.控制总线.一次性令牌.全局锁.领导者选举.分布式会话.集群状态等).为开发分布式应用 ...

  2. JSP JSTL

    JSTL是Sun给JSP制定的一套标准标签库,JS代表JSP,TL即Tag Library. JSTL是一套很古老的标签库了,很多东西都不再适用,这里只介绍几个常用的标签. 使用JSTL需下载添加以下 ...

  3. Alpha4

    一.站立式会议照片 二.工作进展 (1) 昨天已完成的工作 a. 实现用户登录时获取用户信息功能 b. 实现个人目标列表,允许用户在个人目标界面浏览已设置的目标 c. 继续实现目标广场列表 (2)今天 ...

  4. (原)堆叠hourglass网络

    转载请注明出处: https://www.cnblogs.com/darkknightzh/p/11486185.html 论文: https://arxiv.org/abs/1603.06937 官 ...

  5. 第一部分day4-三次登录实验、字符编码

    #-----三次登录实验----- memu = { "陕西":{ "西安市":{ "新城区":["大明宫遗址",&qu ...

  6. 工作不久的安卓开发者,他们是这样规划自己的Android学习路线

    Android开发工作者工作不久的时候,会有一段迷茫期,觉得自己应该再学一点,却不知道从何学起,该怎样规划自己的学习路线呢?今天,我给大家梳理一下Android基础,就像建造房屋一样,要建造一座宏伟的 ...

  7. Android Studio总结

    课程背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,G ...

  8. 使用 python set 去重 速度到底是多快呢???

    这次去测试一下 python 的set去重,速度怎么样? 我们要做的是把文件一次性读取到内存中,然后去重,输出去重的长度. 第一步:对 121w 条数据去重,看去重话费的时间 上证据: 第二步:对 1 ...

  9. Kdevelop的安装-2种方法

    使用 Ubuntu 的自带的源: sudo apt-get update sudo apt-get install kdevelop 这就可以了.update这部,假如不换源,更新非常慢.换源方法很简 ...

  10. arguments简单函数 求整数递加和

    function add(n){if(n == 1) return 1;else return n + arguments.callee(n-1);alert(arguments.callee(1)) ...