一、概念准备

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

  • 类的功能层次结构:假设现在有一个类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. JMeter学习-图形化 HTML 报表概要说明

    JMeter 3.0开始支持动态生成图形化 HTML dashboard报告,当前生成报告有一下两种方式: 1.脚本测试执行结束后,即生成HTML测试报告 2.通过之前生成的测试结果,生成HTML测试 ...

  2. 环境变量方式使用 Secret【转】

    通过 Volume 使用 Secret,容器必须从文件读取数据,会稍显麻烦,Kubernetes 还支持通过环境变量使用 Secret. Pod 配置文件示例如下: 创建 Pod 并读取 Secret ...

  3. vs2010编译C++ 结构体

    //结构体的测试// CTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usi ...

  4. 016.CI4框架CodeIgniter数据库操作之:Insert插入一条数据

    01.在Model中,写入插入的语句 <?php namespace App\Models\System; use CodeIgniter\Model; class User_model ext ...

  5. win10热键体验

    Alt+Tab: 横向显示正在执行的进程 Win+Tab: 3D形式展示正在执行的进程 Win+D:返回桌面(逃领导查电脑和放窥屏尴尬) Win+R: run(直接打开文件开始运行) crtl+Alt ...

  6. go_http

    httpSvr // HandleFunc registers the handler function for the given pattern // in the DefaultServeMux ...

  7. python学习笔记2018-9-17

    1.print("{0:^30}\n{1:^30}\n{1:10}".format("age","name")) {0:^30}中的0是一个 ...

  8. 锤子科技向OpenBSD基金会捐款195 万

    导读 专注于提供 OpenBSD 资讯的网站 OpenBSD Journal 昨日报道了锤子科技成为 OpenBSD 基金会 2019 年首位铱金捐赠者的消息. 根据 OpenBSD Journal ...

  9. Python自学之路

    2020年春节,受新型冠状病毒影响,整个春节假期,全国人民都在恐慌之中,为了避免大家上班相互传染,公司号召国家政策,开始上班日期延迟,在家呆的实在太无聊,突然感觉自己不能浪费这美好的时光,决定学习Py ...

  10. windows平台上运行Flink_转载于CSDN

    Flink安装部署-window 本地部署原创冰上浮云 发布于2019-08-17 15:56:06 阅读数 633 收藏分类专栏: flink版权声明:本文为博主原创文章,遵循 CC 4.0 BY- ...