《Java设计模式》之桥接模式
Bridge模式的概念
Bridge 模式是构造型的设计模式之中的一个。Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而能够保持各部分的独立性以及应对它们的功能扩展。
Bridge模式的应用场景
面向对象的程序设计(OOP)里有类继承(子类继承父类)的概念,假设一个类或接口有多个详细实现子类。假设这些子类具有下面特性:
- 存在相对并列的子类属性。
- 存在概念上的交叉。
- 可变性。
我们就能够用Bridge模式来对其进行抽象与详细。对相关类进行重构。
桥接模式的适用:
你不希望在抽象和它的实现部分之间有一个固定的绑定关系。比如:程序的实现部分在执行时须要被选择或者切换。
类的抽象以及它的实现都应该能够通过生成子类的方法加以扩充。
这时Bridge模式使你能够对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
对一个抽象实现的改动须要对客户不产生影响,即客户的代码不必又一次编译。
有很多类要生成。这样的情况下你必须将一个对象分解成两个部分。这样的类层次结构为“嵌套的普化”。
你想在多个对象间共享实现(可能使用引用计数),但同一时候要求客户并不知道这一点。
生活中的一个样例:
拿汽车在路上行驶的来说。
既有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在快速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型。它们所行驶的环境(路)也有不同类型,在软件系统中就要适应两个方面(不同车型,不同道路)的变化,如何实现才干应对这样的变化呢?
概述:
在软件系统中。某些类型因为自身的逻辑。它具有两个或多个维度的变化,那么怎样应对这样的“多维度的变化”?怎样利用面向对象的技术来使得该类型可以轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
意图:
将抽象部分与实现部分分离,使它们都能够独立的变化。
——《设计模式》GOF
上面这些话我也没看懂。
。太抽象了,可是一看代码你就明确是怎么回事了。
结构图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFzb24wNTM5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" style="border:none; max-width:100%">
传统的做法:
通过类继承的方式来做上面的样例;
先看一下类结构图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFzb24wNTM5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" style="border:none; max-width:100%">
代码实现:
- //基类 路
- class Road {
- void run() {
- System.out.println("路");
- }
- }
- //市区街道
- class Street extends Road {
- void run() {
- System.out.println("市区街道");
- }
- }
- //快速公路
- class SpeedWay extends Road {
- void run() {
- System.out.println("快速公路");
- }
- }
- //小汽车在市区街道行驶
- class CarOnStreet extends Street {
- void run() {
- System.out.println("小汽车在市区街道行驶");
- }
- }
- //小汽车在快速公路行驶
- class CarOnSpeedWay extends SpeedWay {
- void run() {
- System.out.println("小汽车在快速公路行驶");
- }
- }
- //公交车在市区街道行驶
- class BusOnStreet extends Street {
- void run() {
- System.out.println("公交车在市区街道行驶");
- }
- }
- //公交车在快速公路行驶
- class BusOnSpeedWay extends SpeedWay {
- void run() {
- System.out.println("公交车在快速公路行驶");
- }
- }
- //測试
- public static void main(String[] args) {
- //小汽车在快速公路行驶
- CarOnSpeedWay carOnSpeedWay = new CarOnSpeedWay();
- carOnSpeedWay.run();
- //公交车在市区街道行驶
- BusOnStreet busOnStreet = new BusOnStreet();
- busOnStreet.run();
- }
缺点:
可是我们说这种设计是脆弱的,细致分析就能够发现,它还是存在非常多问题,首先它在遵循开放-封闭原则的同一时候。违背了类的单一职责原则,即一个类仅仅有一个引起它变化的原因。而这里引起变化的原因却有两个。即路类型的变化和汽车类型的变化;其次是反复代码会非常多,不同的汽车在不同的路上行驶也会有一部分的代码是同样的;
再次是类的结构过于复杂,继承关系太多,难于维护。最后最致命的一点是扩展性太差。假设变化沿着汽车的类型和不同的道路两个方向变化,我们会看到这个类的结构会迅速的变庞大。
应用设计模式
桥接模式(Bridge)来做;
先看一下类结构图:
代码实现:
- abstract class AbstractRoad{
- AbstractCar aCar;
- void run(){};
- }
- abstract class AbstractCar{
- void run(){};
- }
- class Street extends AbstractRoad{
- @Override
- void run() {
- // TODO Auto-generated method stub
- super.run();
- aCar.run();
- System.out.println("在市区街道行驶");
- }
- }
- class SpeedWay extends AbstractRoad{
- @Override
- void run() {
- // TODO Auto-generated method stub
- super.run();
- aCar.run();
- System.out.println("在快速公路行驶");
- }
- }
- class Car extends AbstractCar{
- @Override
- void run() {
- // TODO Auto-generated method stub
- super.run();
- System.out.print("小汽车");
- }
- }
- class Bus extends AbstractCar{
- @Override
- void run() {
- // TODO Auto-generated method stub
- super.run();
- System.out.print("公交车");
- }
- }
- public static void main(String[] args){
- AbstractRoad speedWay = new SpeedWay();
- speedWay.aCar = new Car();
- speedWay.run();
- AbstractRoad street = new Street();
- street.aCar = new Bus();
- street.run();
- }
能够看到。通过对象组合的方式,Bridge 模式把两个角色之间的继承关系改为了耦合的关系。从而使这两者能够从容自若的各自独立的变化,这也是Bridge模式的本意。
这样添加了客户程序与路与汽车的耦合。
事实上这种操心是没有必要的,由于这种耦合性是由于对象的创建所带来的,全然能够用创建型模式去解决。在应用时结合创建型设计模式来处理详细的问题。
应用设计模式:
桥接模式(Bridge)来做(多维度变化);
结合上面的样例,添加一个维度"人",不同的人开着不同的汽车在不同的路上行驶(三个维度);
结合上面添加一个类"人",并又一次调用.
代码实现:
- abstract class People {
- AbstractRoad road;
- void run() {}
- }
- class Man extends People{
- @Override
- void run() {
- // TODO Auto-generated method stub
- super.run();
- System.out.print("男人开着");
- road.run();
- }
- }
- class Woman extends People{
- @Override
- void run() {
- // TODO Auto-generated method stub
- super.run();
- System.out.print("女人开着");
- road.run();
- }
- }
- public static void main(String[] args) {
- AbstractRoad speedWay = new SpeedWay();
- speedWay.aCar = new Car();
- People man = new Man();
- man.road = speedWay;
- man.run();
- }
效果及实现要点:
1.Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现能够沿着各自的维度来变化。
2.所谓抽象和实现沿着各自维度的变化,即“子类化”它们。得到各个子类之后,便能够随意它们。从而获得不同路上的不同汽车。
3.Bridge模式有时候类似于多继承方案,可是多继承方案往往违背了类的单一职责原则(即一个类仅仅有一个变化的原因),复用性比較差。Bridge模式是比多继承方案更好的解决方法。
4.Bridge模式的应用一般在“两个很强的变化维度”,有时候即使有两个变化的维度。可是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。
适用性:
在下面的情况下应当使用桥梁模式:
1.假设一个系统须要在构件的抽象化角色和详细化角色之间添加很多其它的灵活性,避免在两个层次之间建立静态的联系。
2.设计要求实现化角色的不论什么改变不应当影响client,或者说实现化角色的改变对client是全然透明的。
3.一个构件有多于一个的抽象化角色和实现化角色。系统须要它们之间进行动态耦合。
4.尽管在系统中使用继承是没有问题的。可是因为抽象化角色和详细化角色须要独立变化,设计要求须要独立管理这两者。
总结:
Bridge模式是一个很实用的模式,也很复杂。它很好的符合了开放-封闭原则和优先使用对象,而不是继承这两个面向对象原则。
本文借鉴文章:
http://blog.csdn.net/jason0539/article/details/22568865
《Java设计模式》之桥接模式的更多相关文章
- java设计模式7——桥接模式
java设计模式7--桥接模式 1.桥接模式介绍 桥接模式是将抽象部分与它的实现部分分离,使他们都可以独立的变化.它是一种对象结构型模式,又称为柄体模式或接口模式. 2.解决问题 2.1.将复杂的组合 ...
- java设计模式之桥接模式
桥接模式 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦.这种模式涉及到一个作为桥接的 ...
- Java设计模式:桥接模式
问题提出 生活中有很多事物集合,设为A1,A2......Am ,而每个事物都有功能F1,F2....Fn. 例如邮局的发送业务.简单模拟有两类事物:信件和包裹,均有平邮和挂号邮寄功能.程序设计中如何 ...
- Java设计模式应用——桥接模式
性能管理系统中,数据产生后需要经过采集,汇聚,入库三个流程,用户才能查询使用. 采集可以是snmp采集,也可以是ems采集:汇聚可以使storm汇聚,也可以是spark汇聚:入库可以是hdfs入库,也 ...
- java设计模式之-----桥接模式
一.概念定义 将抽象部分和实现部分分离,使他们都可以独立的变化.(这句话有点抽象啊..) 在软件系统中,某种类型由于自身逻辑,具有多个维度的变化,如何利用面向对象的技术来使得该类型沿着多方向变化,而又 ...
- JAVA设计模式之桥接模式(bridge)
桥接模式: 分离抽象与具体实现,让他们可以独自发展,防止类爆炸 场景: 过年走亲戚是我们中国人传统的习俗,走亲戚那就少不了要买东西(苹果,牛奶等等),这些具体的东西就是具体的类 蒙牛牛奶,有机苹果,有 ...
- 八戒转世投胎竟然是Java设计模式:桥接模式
目录 示例 代码实例 桥接模式 定义 意图 主要解决问题 何时使用 优缺点 八戒转世投胎的故事 示例 请开发一个画图程序,可以画各种颜色不同形状的图形,请用面向对象的思 想设计图形 分析: 1.比如有 ...
- java面试题之----jdbc中使用的设计模式(桥接模式)
1.JDBC(JavaDatabase Connectivity) JDBC是以统一方式访问数据库的API. 它提供了独立于平台的数据库访问,也就是说,有了JDBC API,我们就不必为访问Oracl ...
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
随机推荐
- caioj 1080 动态规划入门(非常规DP4:乘电梯)(dp数组更新其他量)
我一开始是这么想的 注意这道题数组下标是从大到小推,不是一般的从小到大推 f[i]表示从最高层h到第i层所花的最短时间,答案为f[1] 那么显然 f[i] = f[j] + wait(j) + (j ...
- Opencv 三次样条曲线(Cubic Spline)插值
本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/47707679 1.样条曲线简介 样条曲 ...
- HDFS文件系统上传时序图 PB级文件存储时序图
自己设计的时序图. 来自为知笔记(Wiz)
- js使用offsetHeight获取div高度为0的问题
今晚试了好久没弄出来,后来获取子一层的div就能获取到高度了 我的情况是这样的:我在最外面写一个<div id="mainBody">, 里面写bootstrap的d ...
- 自己定义View之Chart图标系列(1)——点阵图
近期要做一些图表类的需求,一開始就去github上看了看,发现开源的图表框架还是蛮多的.可是非常少有全然符合我的需求的.另外就是使用起来比較麻烦.所以就决定自己来造轮子了~~~ 今天要介绍的就是And ...
- 动态网页爬取样例(WebCollector+selenium+phantomjs)
目标:动态网页爬取 说明:这里的动态网页指几种可能:1)须要用户交互,如常见的登录操作:2)网页通过JS / AJAX动态生成.如一个html里有<div id="test" ...
- Centos7 zabbix3.4.6的安装部署 (二)
接着安装zabbix客户端 直接安装在服务器上 监控服务器 ip 192.168.161.25 yum -y install zabbix-agent #通过Yum安装zabbix客户端 接着配置za ...
- SQL Server 2000数据库备份与恢复图解
SQL Server 2000数据库备份与恢复图解 四个步骤:1.安装sql server 2000 2.数据库设置: 3.建立自动备份 4.还原数据库 具体图片见附件 本文出自 "李 ...
- Android开发当中Parcelable接口的使用
本文转载于:http://www.2cto.com/kf/201205/132814.html 本文稍微做了些修改 android提供了一种新的类型:Parcel.本类被用作封装数据的容器,封装后的数 ...
- 如何更新 CentOS 镜像源
话不多说, 直接上教程. 首先备份/etc/yum.repos.d/CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.rep ...
