一、概念准备

  在理解桥接模式之前,先要理解面向对象程序设计中的两个概念:

  • 类的功能层次结构:假设现在有一个类Something,这个类有一些成员属性和成员方法,但是现有的功能不能满足要求,因此我们想扩展这个类,给这个类创建一个子类SomethingBetter来继承它,并在子类中添加更多属性和方法。像这样不同的功能位于不同的类继承结构中,就构成了类的功能层次结构。
  • 类的实现层次结构:回顾一下抽象类的作用,抽象类声明抽象方法(定义了方法接口API),然后在继承它的子类中实现相关方法。由于我们将方法定义和实现分离到了不同的类中,从而实现了类的高可替换性,并有了模板Template Method方法模式。虽然这里也有父类和子类的继承关系,但是这里的继承并不是为了增加新功能,而是为了完成“定义——实现 分离”中的实现环节。这种层次结构就是类的实现层次接口。

二、模式说明

  如果类的设计都只有一层(程序中自定义的类不存在继承关系),这时候类的功能层次结构和实现层次结构是混杂在一起的,也很难扩展(无法确定应该继承哪个类来扩展功能,同一个方法如果想替换其实现也无法做到)。因此需要按照上面说的,将类的功能层次和实现层次分开,为了在分开后能继续保持一定的联系,这时候就需要一个桥梁,将它们连接起来。(Bridge也有桥梁的意思,连接两个事物)

三、代码示例

  在下面的桥接模式代码示例中,着重关注哪些时功能层次,哪些是实现层次,二者又是如何桥接起来的。

1、类的功能层次结构

Display类:Display类的功能是抽象的,负责“显示”一些东西,它位于功能层次结构的最上层。open、print、close这三个方法是Display类提供的接口,它们定义了显示的步骤,这三个方法调用的是Display实现类的对象。

package com.designpattern.cn.bridgepattern;

public class Display {
private DisplayImpl impl;
public Display(DisplayImpl impl){
this.impl = impl;
}
public void open(){
impl.rawOpen();
}
public void print(){
impl.rawPrint();
}
public void close(){
impl.rawClose();
}
public final void display(){
open();
print();
close();
}
}

CountDisplay类:CountDisplay类在Display类的基础上增加了一个新功能,具有“只显示规定次数”的功能。因此,这属于“类的功能层次范畴”。

package com.designpattern.cn.bridgepattern;

public class CountDisplay extends Display {
public CountDisplay(DisplayImpl impl){
super(impl);
}
public void multiDisplay(int times){
open();
for(int i=0; i < times; i++){
print();
}
close();
}
}

2、类的实现层次结构

DisplayImpl类:位于“类的实现层次结构”的最上层。DisplayImpl是抽象类,声明了rawOpen、rawPrint、rawClose三个抽象方法。

package com.designpattern.cn.bridgepattern;

public abstract class DisplayImpl {
public abstract void rawOpen();
public abstract void rawPrint();
public abstract void rawClose();
}

StringDisplayImpl类:它是仙子字符串的类,但它并不是直接显示字符串,而是继承了DisplayImpl类,作为子类来使用rawOpen、rawPrint、rawClose三个方法显示字符串。

package com.designpattern.cn.bridgepattern;

public class StringDisplayImpl extends DisplayImpl {
private String string;
private int width;
public StringDisplayImpl(String string){
this.string = string;
this.width = string.getBytes().length;
}
@Override
public void rawOpen(){
printLine();
}
@Override
public void rawPrint(){
System.out.println("|" + string + "|");
}
@Override
public void rawClose() {
printLine();
} private void printLine(){
System.out.print("+");
for(int i = 0; i < width; i++){
System.out.println("-");
}
System.out.println("+");
}
}

3、Main类测试结果

四、模式类图

五、模式中的角色

  • Abstraction抽象化:类的功能层次的最上层,它使用Implementor角色的方法定义了基本功能,如上面的Display类。
  • RefinedAbstraction改善后的抽象化:增加了Abstraction的功能,如上面的CountDisplay类。
  • Implementor实现者:类的实现层次结构最上层,定义了用于实现Abstraction的角色的接口方法,如上面的DisplayImpl类。
  • ConcreteImplementor具体实现者:负责实现Implementor角色定义的接口方法,如上面的StringDisplayImpl类。

那么,这其中的桥梁Bridge是什么呢?对于示例程序,Display类和DisplayImpl是如何关联的,从程序中看出,这里的桥梁应该是impl字段。

六、相关的设计模式

  • 模板方法Template Method模式:模板方法模式就是使用了桥接模式中的类的实现层次结构。父类调用抽象方法,子类实现具体方法。
  • 抽象工厂Abstract Factory模式:可以使用抽象工厂设计出更好的ConcreteImplementor类。
  • 适配器Adapter模式:桥接模式连接了类的结构层次和实现层次,适配器模式则将功能类似,但是接口不匹配的类结合在一起。

七、扩展

  • 采用bridge桥接模式分离功能层次和实现层次,更有利于类的扩展,如果要增加功能,只需在功能层次这一侧做修改,无需调整实现层次,并且所有的实现层次都能利用增加的功能。
  • 继承是强关联,委托是弱关联。继承可以方便的得到功能更强的类,但是一旦使用继承,则在类之间形成了强关联关系,如果想改变或者替换其中的一个类,就必须修改类的代码。上面的例子中,使用了委托,只有当Display类的实例生成时,才作为参数,与被传入的类构成关联关系(示例程序中,只有Main类生成Display类和CountDisplay类的实例时,才将StringDisplayImpl类的实例作为参数传递给Display类和CountDisplay类)。除了StringDisplayImpl类,我们可以使用任意一个ConcreteImplementor角色传递给Display类和CountDisplay类,就能很容易的改变实现(只需修改Main类,Display类和DisplayImpl无需任何修改)。

一天一个设计模式——Bridge桥接模式的更多相关文章

  1. C++设计模式-Bridge桥接模式

    作用:将抽象部份与它的实现部份分离,使它们都可以独立地变化. 将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式 ...

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

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

  3. 设计模式07: Bridge 桥接模式(结构型模式)

    Bridge 桥接模式(结构型模式) 抽象与实现 抽象不应该依赖于实现细节,实现细节应该依赖于抽象. 抽象B稳定,实现细节b变化 问题在于如果抽象B由于固有的原因,本身并不稳定,也有可能变化,怎么办? ...

  4. Bridge桥接模式(设计模式11)

    在没有使用桥接模式: 扩展新问题(类归属膨胀问题) 1增加性的电脑类型,要增加每个品牌下面的类 2如果要增加一个新的电脑品牌,要增加美中电脑类型的类 违背单一职责原则: · 一个类:联想笔记本,有两个 ...

  5. Bridge桥接模式(结构型模式)

    现有一个需求,一个游戏系统需要构建不同风格的房屋,暂不考虑其他设计模式,需要能实现在PC端.移动端....等等多个平台的构建.最简单的实现方式如下: /// <summary> /// 房 ...

  6. java面试题之----jdbc中使用的设计模式(桥接模式)

    1.JDBC(JavaDatabase Connectivity) JDBC是以统一方式访问数据库的API. 它提供了独立于平台的数据库访问,也就是说,有了JDBC API,我们就不必为访问Oracl ...

  7. php设计模式之桥接模式

    php设计模式之桥接模式 一.概述 桥接模式:将两个原本不相关的类结合在一起,然后利用两个类中的方法和属性,输出一份新的结果. 其实就是讲不相关的东西通过类(本例中是SendInfo)结合在一起,从而 ...

  8. java设计模式之-----桥接模式

    一.概念定义 将抽象部分和实现部分分离,使他们都可以独立的变化.(这句话有点抽象啊..) 在软件系统中,某种类型由于自身逻辑,具有多个维度的变化,如何利用面向对象的技术来使得该类型沿着多方向变化,而又 ...

  9. java设计模式7——桥接模式

    java设计模式7--桥接模式 1.桥接模式介绍 桥接模式是将抽象部分与它的实现部分分离,使他们都可以独立的变化.它是一种对象结构型模式,又称为柄体模式或接口模式. 2.解决问题 2.1.将复杂的组合 ...

随机推荐

  1. tomcat报错catalina.sh: line 401: /usr/java/jdk1.7.52/bin/java: No such file or directory(转)

    原文:https://blog.csdn.net/reblue520/article/details/52588825 将生产服务器的Tomcat目录打包过来后解压后,启动Tomcat后,发现如下问题 ...

  2. arm linux 移植 rsync

    背景: 在产品开发中可以使用rsync进行大文件的拷贝,断点续传. host平台 :Ubuntu 16.04 arm平台 : 3531d   rsync   :3.1.3 arm-gcc :4.9.4 ...

  3. MyBatis源码部分简单地解析

    . 一.解析xml: > org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream, java.l ...

  4. 使用PYaudio录制音频和视频(自己)

    参考:https://blog.csdn.net/zhaoyun_zzz/article/details/84341801 音频录制:简洁版 import pyaudioimport waveimpo ...

  5. UML图表示类之间的关系

    一.泛化(Generanization) 图: 泛化简单的说就是继承关系,在java中就是extend.表示一般与特殊的关系.如鸭子是鸟的一种,即有鸭子的特性也有鸟的共性.用带空心的三角箭头的实线指向 ...

  6. centos7下安装maven

    步骤1:在home目录下解压apache-maven-3.5.0-bin.tar.gz安装包 [root@model ~]# -bin.tar.gz 步骤2:创建/maven目录并将解压后的文件夹移至 ...

  7. NO13 Linux的基础优化-关闭SELinux功能-Linux的7种运行级别-防火墙设置-中文显示设置

    壹  安装Linux系统后调优及安全设置: 1 关闭SELinux功能: [root@localhost data]# sed 's#SELINUX=enforcing#SELINUX=disable ...

  8. php5.3不支持 ereg、ereg_replace等函数问题

    在php5.3环境下运行oscommerce,常常会出现Deprecated: Function ereg() is deprecated in...和Deprecated: Function ere ...

  9. node重点 模块

    node模块 1.全局模块(对象)(像js中的window document) 定义:何时何地都可以访问,不需要引用 1.process.env 环境变量 计算机属性 高级系统设置 高级 环境变量 作 ...

  10. PHPmyadmin Getshell(10.25 第二十七天)

    PHPmyadmin Getshell的方法(1)show global variables like '% secure-file-priv%' 如果该参数设置为空或者指定的文件夹可以利用,然后写木 ...