1.1概述

将抽象部分与它的实现部分分离,使他们都可以独立地变化。这就是桥接模式的定义。

抽象类或接口中可以定义若干个抽象方法,习惯上将抽象方法称作操作。抽象类或接口使程序的设计者忽略操作的细节,即不必考虑这些操作是如何实现的,当用户程序面向抽象类或接口时,就不会依赖具体的实现,使系统具有很好的扩展性。但是,抽象类中的抽象方法总归是需要子类去实现的,在大多数情况下抽象类的子类完全可以胜任这样的工作,但是在某些情况下,子类可能会遇到一些难以处理的问题。

例如,电视台系统中有一个抽象类CCTV,该类有一个抽象方法abstract void makeProgram()。现在为了满足某些用户看电视剧的需求,这里给出了CCTV类的子类:CCTV8,该类的实例调用makeProgram()方法制作电视剧节目,因此子类CCTV8必须实现父类的makeProgram()方法,比如使用该方法制作出若干帧影像。子类CCTV8的makeProgram()方法在制作出第一帧影像后,比如在第一帧影像显示“CCTV8”,马上就发现以下两个问题:

(1)从第2帧开始应当是电视剧中的影像,而这样的影像不应当由CCTV8类的makeProgram()方法负责制作。

(2)如果CCTV8在makeProgram()方法中强行给出了第2帧以后的各个影像,那么用户使用CCTV8类的实例看到的电视剧是一个固定的电视剧,如果有其他用户想看新的电视剧,系统就必须新增新的CCTV子类,这对电视台系统是一个非常不合理的一种设计,因为CCTV类应当只有一个负责制作“电视剧”节目的子类:CCTV8,而不是多个,也就是说,不能因为一个新的用户要看不同的电视剧,就要出现一个专门为该用户制作“电视剧”节目的子类。

针对上述问题,应当将实现和抽象放在两个不同的类层次中,从而使他们可独立的改变,即将一个抽象类中抽象方法的重要实现部分交给另外一个抽象类的子类或实现另外一个接口的类。比如,对于上述问题,应当将makeProgram()方法的实现交给另外一个抽象类:Program,该类定义了制作影像的makeTVfilm()方法。

我们应当重新设计抽象类CCTV类,使该类包含Program的引用,这就可以使CCTV类的子类CCTV8在实现makeProgram()方法时,将该方法的重要实现部分交给Program类的makeTVfilm()方法,即委托给Program子类的实例调用makeTVfilm()方法。

我们称CCTV类和Program类之间的关系是桥接关系,也即是说,CCTV类的子类CCTV8仅仅在CCTV类和Program类之间起到一个“桥接”的作用,具体类关系如下图一所示:

图一:电视节目与电视剧制作的桥接关系

1.2模式的结构

桥接模式包括以下四种角色:

(1)抽象(Abstration):是一个抽象类,该抽象类含有Implementor声明的变量,即维护一个Implementor类型对象。

(2)实现者(Implementor):实现者角色是一个接口(抽象类),该接口(抽象类)中的方法不一定与Abstration类中方法一致。Implementor接口(抽象类)负责定义基本操作,而Abstration类负责定义基于这些基本操作的较高层次的操作。

(3)细化抽象(Refined Abstration):细化抽象是抽象角色的一个子类,该子类在重写(覆盖)抽象角色中的抽象方法时,在给出一些必要的操作后,将委托所维护Implementor类型对象调用相应的方法。

(4)具体实现者(Concrete Implementor):具体实现者是实现(扩展)Implementor接口(抽象类)的类。

桥接模式结构的类图如下图二所示:

图二:桥接模式的类图

1.3桥接模式的优点

(1)桥接模式分离实现与抽象,使抽象和实现可以独立的扩展。当修改实现的代码时,不影响抽象的代码,反之也一样。

(2)满足开-闭原则。抽象和实现者处在同层次,使系统可独立地扩展者两个层次。增加新的具体实现者,不需要修改细化对象,反之增加新的细化对象也不需要修改具体实现。

1.4适合使用桥接模式的情景

(1)不想让抽象和某些重要的实现代码是固定绑定关系,这部分实现可运行时动态决定。

(2)抽象和实现者都可以继承的方法独立地扩充而互不影响,程序在运行期间可能需要动态的将一个抽象的子类的实例与一个实现者的子类的实例进行组合。

(3)希望对实现者层次的代码的修改对抽象层不产生影响,即抽象层的代码不必重新编译,反之亦然。

1.5桥接模式的使用

以下通过一个简单的问题来描述怎样使用桥接模式,这个简单的问题是:计算建筑楼房的成本。

首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:

(1)抽象(Abstraction)

本问题中,抽象角色是ArchitectureCose类,代码如下:

package com.liuzhen.sixteen_bridge;public abstract class ArchitectureCose {BuildingDesign design;double unitPrice;public abstract double giveCost();
}

(2)实现者(Implementor)

对于本问题,实现者是BuildingDesign接口,BuildingDesign接口的代码如下:

package com.liuzhen.sixteen_bridge;public interface BuildingDesign {public double computerArea();
}

(3)细化抽象(Refined Abstraction)

对于本问题,细化抽象角色是BuildingCose类,该类是ArchitectureCose类的子类。BuildingCose类在实现父类ArchitectureCose中的giveCose()方法时,需要根据建筑物的总面积和每平方米的造价给出整个建筑物的建造成本。但是,建筑物的建筑面积应当由建筑设计者提供,即建筑设计者负责计算建筑物的总面积,因此giveCose()的基本实现部分应当由一个和ArchitectureCose类同层次的BuildingDesign接口负责,即由实现BuildingDesign接口的类的实例负责面积的计算,而BuildingCose类负责定义基于这些基本操作的较高层次的操作,因此,BuildingCose类在实现giveCose()方法时将基于实现BuildingDesign接口的类的实例所给出建筑物面积来计算建造成本。BuildingCose类的代码如下:

package com.liuzhen.sixteen_bridge;public class BuildingCose extends ArchitectureCose{BuildingCose(BuildingDesign design, double unitPrice){this.design = design;this.unitPrice = unitPrice;}public double giveCost(){double area = design.computerArea();return area*unitPrice;}
}

(4)具体实现者(Concrete Implementor)

对于本问题,具体实现者是HouseDesign类的实例,HouseDesign类的代码如下:

package com.liuzhen.sixteen_bridge;public class HouseDesign implements BuildingDesign{double width, length;int floorNumber;HouseDesign(double width, double length, int floorNumber){this.width = width;this.length = length;this.floorNumber = floorNumber;}public double computerArea(){return width*length*floorNumber;}
}

(5)具体使用

通过SixteenApplication类来具体实现上述相关类和接口,来实现桥接模式的运用,其代码如下:

package com.liuzhen.sixteen_bridge;public class SixteenApplication {public static void main(String[] args){double width = 63, height = 30;int floorNumber = 8;double unitPrice = 6867.38;BuildingDesign design = new HouseDesign(width, height, floorNumber);System.out.println("宽:"+width+"米,高:"+height+"米,层数为:"+floorNumber);ArchitectureCose cost = new BuildingCose(design,unitPrice);double price = cost.giveCost();System.out.println("每平方米造价:"+unitPrice+"元,商业楼的建设成本:"+price);}
}

运行结果:

宽:63.0米,高:30.0米,层数为:8
每平方米造价:6867.38元,商业楼的建设成本:1.0383478560000001E8

参考资料:

      1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5

设计模式学习笔记(十六:桥接模式)相关推荐

  1. 设计模式学习笔记之(桥接模式brid…

    首先桥接模式解决的是抽象和具体实现相分离的问题.想象下这种常见的场景车在路上跑,这是一个行为,但是具体是什么车之什么路上跑就跟具体的使用场景相关联了.比如说可能是宝马车之高速公路上跑,也有可能是 公交 ...

  2. 设计模式学习笔记十五——Command模式

    动机:将一组行为抽象为对象,实现行为请求者和行为实现者之间的解耦,并且支持对行为进行记录.撤销.重做.事务等处理. 场景:考虑一系列文档操作:打开.复制.剪切.粘帖. 结构 代码实现 /**//*   ...

  3. java 设计模式学习笔记十 bridge桥模式

    bridge桥模式 将抽象和行为划分开来,各自独立但能动态结合 抽象的接口 /**  * 咖啡抽象类  *   * @time 下午09:14:27  * @author retacn yue  * ...

  4. 设计模式学习笔记——享元(Flyweight)模式

    设计模式学习笔记--享元(Flyweight)模式 @(设计模式)[设计模式, 享元模式, flyweight] 设计模式学习笔记享元Flyweight模式 基本介绍 享元案例 类图 实现代码 Big ...

  5. 设计模式学习笔记——中介者(Mediator)模式

    设计模式学习笔记--中介者(Mediator)模式 @(设计模式)[设计模式, 中介者模式, Mediator] 设计模式学习笔记中介者Mediator模式 基本介绍 中介者案例 类图 实现代码 Me ...

  6. 设计模式学习笔记——单例(Singleton)模式

    设计模式学习笔记--单例(Singleton)模式 @(设计模式)[设计模式, 单例模式, Singleton, 懒汉式, 饿汉式] 设计模式学习笔记单例Singleton模式 基本介绍 单例案例 类 ...

  7. 电脑安装python3.74_python3.4学习笔记(十六) windows下面安装easy_install和pip教程

    python3.4学习笔记(十六) windows下面安装easy_install和pip教程 easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安 ...

  8. Polyworks脚本开发学习笔记(十六)-用C#进行Polyworks二次开发

    Polyworks脚本开发学习笔记(十六)-用C#进行Polyworks二次开发 Polyworks支持C#二次开发,用对应的SDK文档试着做一下开发样例. 新建一个C#项目,在解决方案中右键添加引用 ...

  9. 设计模式学习笔记--Mediator 中介者模式

    我们知道面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成.当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点).而当对象的数量增加时,这种直接交互会导致对象之间复杂的.混乱的引 ...

  10. 设计模式学习笔记--Flyweight享元模式

    Flyweight模式也叫享元模式,是由GoF提出的23种设计模式中的一种.Flyweight模式是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用,所以叫享元.   此模式解决的是由于大量 ...

最新文章

  1. win10 计算机网络密码,win10系统电脑如何查看wifi密码 win10系统电脑查看wifi密码方法【介绍】...
  2. jpg图片与jpeg图片格式的区别(没有区别,.jpg只是扩展名.jpeg的缩写)
  3. kindle的xray怎么用_Xray使用的一些经验分享
  4. ecshop模板支持php,[老杨原创]关于ECSHOP模板架设的服务器php版本过高报错的解决方法集合...
  5. C#正则表达式判断输入的是不是数字
  6. apache gobblin mysql_gobblin简单使用
  7. 如何在JavaScript中使用when()有条件地更改值
  8. Unreal Engine 4切换默认Camera实现
  9. Win10下Pytorch的安装和使用[斗之力三段]
  10. WEB服务器Nginx WINDOWS最简部署
  11. Visio使用技巧总结
  12. WinRunner的工作流程
  13. 算法 动画算法 算法动画 动画原理——总体概览图
  14. linux木马查杀工具,【Kali】linux木马查杀
  15. php 504网关,php出现504错误的原因是什么
  16. 金融人都在选择的硕士项目---中国人民大学与加拿大女王大学金融硕士
  17. kubeadm工作原理-kubeadm init原理分析-kubeadm join原理分析
  18. 富士胶片集团发布2021财年上半年度财报;罗克韦尔自动化推出新的远程访问解决方案 | 全球TMT...
  19. Ph P Manual
  20. Markdown中空格和换行

热门文章

  1. 前端一HTML:十七:背景
  2. spring boot三:spring boot的hello, world
  3. 单页面抓图并且保存的爬虫
  4. Gradle脚本基础全攻略
  5. 阿里内核月报2015年03月
  6. 格式化大容量硬盘为fat32
  7. MongoDB空间分配
  8. 安卓开发-Activity中finish() onDestroy() 和System.exit()的区别
  9. yii和thinkphp杂谈
  10. nutch-site参数配置