开发者社区> 聚优云惠> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Java 设计模式之桥接模式

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfeng812/article/details/8949352 《设计模式》中对桥接模式的定义为: 将抽象部分与它的实现部分分离,使他们可以独立地变化。
+关注继续查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfeng812/article/details/8949352

《设计模式》中对桥接模式的定义为:
将抽象部分与它的实现部分分离,使他们可以独立地变化。别名为:Handle/Body。
Bridge模式是构造型的设计模式之一。Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。

结构如下图所示:

3.1  认识桥接模式

(1)什么是桥接
        在桥接模式里面,不太好理解的就是桥接的概念,什么是桥接?为何需要桥接?如何桥接?把这些问题搞清楚了,也就基本明白桥接的含义了。
        一个一个来,先看什么是桥接?所谓桥接,通俗点说就是在不同的东西之间搭一个桥,让他们能够连接起来,可以相互通讯和使用。那么在桥接模式中到底是给什么东西来搭桥呢?就是为被分离了的抽象部分和实现部分来搭桥,比如前面示例中抽象的消息和具体消息发送之间搭个桥。
        但是这里要注意一个问题:在桥接模式中的桥接是单向的,也就是只能是抽象部分的对象去使用具体实现部分的对象,而不能反过来,也就是个单向桥。


(2)为何需要桥接
        为了达到让抽象部分和实现部分都可以独立变化的目的,在桥接模式中,是把抽象部分和实现部分分离开来的,虽然从程序结构上是分开了,但是在抽象部分实现的时候,还是需要使用具体的实现的,这可怎么办呢?抽象部分如何才能调用到具体实现部分的功能呢?很简单,搭个桥不就可以了,搭个桥,让抽象部分通过这个桥就可以调用到实现部分的功能了,因此需要桥接。

(3)如何桥接
        这个理解上也很简单,只要让抽象部分拥有实现部分的接口对象,这就桥接上了,在抽象部分就可以通过这个接口来调用具体实现部分的功能。也就是说,桥接在程序上就体现成了在抽象部分拥有实现部分的接口对象,维护桥接就是维护这个关系。


(4)独立变化
        桥接模式的意图:使得抽象和实现可以独立变化,都可以分别扩充。也就是说抽象部分和实现部分是一种非常松散的关系,从某个角度来讲,抽象部分和实现部分是可以完全分开的,独立的,抽象部分不过是一个使用实现部分对外接口的程序罢了。
        如果这么看桥接模式的话,就类似于策略模式了,抽象部分需要根据某个策略,来选择真实的实现,也就是说桥接模式的抽象部分相当于策略模式的上下文。更原始的就直接类似于面向接口编程,通过接口分离的两个部分而已。但是别忘了,桥接模式的抽象部分,是可以继续扩展和变化的,而策略模式只有上下文,是不存在所谓抽象部分的。
        那抽象和实现为何还要组合在一起呢?原因是在抽象部分和实现部分还是存在内部联系的,抽象部分的实现通常是需要调用实现部分的功能来实现的。


(5)动态变换功能
        由于桥接模式中的抽象部分和实现部分是完全分离的,因此可以在运行时动态组合具体的真实实现,从而达到动态变换功能的目的。
        从另外一个角度看,抽象部分和实现部分没有固定的绑定关系了,因此同一个真实实现可以被不同的抽象对象使用,反过来,同一个抽象也可以有多个不同的实现。就像前面示例的那样,比如:站内短消息的实现功能,可以被普通消息、加急消息或是特急消息等不同的消息对象使用;反过来,某个消息具体的发送方式,可以是站内短消息,或者是Email,也可以是手机短消息等具体的发送方式。

(6)退化的桥接模式
        如果Implementor仅有一个实现,那么就没有必要创建Implementor接口了,这是一种桥接模式退化的情况。这个时候Abstraction和Implementor是一对一的关系,虽然如此,也还是要保持它们的分离状态,这样的话,它们才不会相互影响,才可以分别扩展。
        也就是说,就算不要Implementor接口了,也要保持Abstraction和Implementor是分离的,模式的分离机制仍然是非常有用的。

(7)桥接模式和继承
        继承是扩展对象功能的一种常见手段,通常情况下,继承扩展的功能变化纬度都是一纬的,也就是变化的因素只有一类。
        对于出现变化因素有两类的,也就是有两个变化纬度的情况,继承实现就会比较痛苦。比如上面的示例,就有两个变化纬度,一个是消息的类别,不同的消息类别处理不同;另外一个是消息的发送方式。
        从理论上来说,如果用继承的方式来实现这种有两个变化纬度的情况,最后实际的实现类应该是两个纬度上可变数量的乘积那么多个。比如上面的示例,在消息类别的纬度上,目前的可变数量是3个,普通消息、加急消息和特急消息;在消息发送方式的纬度上,目前的可变数量也是3个,站内短消息、Email和手机短消息。这种情况下,如果要实现全的话,那么需要的实现类应该是:3 X 3 = 9个。
        如果要在任何一个纬度上进行扩展,都需要实现另外一个纬度上的可变数量那么多个实现类,这也是为何会感到扩展起来很困难。而且随着程序规模的加大,会越来越难以扩展和维护。
        而桥接模式就是用来解决这种有两个变化纬度的情况下,如何灵活的扩展功能的一个很好的方案。其实,桥接模式主要是把继承改成了使用对象组合,从而把两个纬度分开,让每一个纬度单独去变化,最后通过对象组合的方式,把两个纬度组合起来,每一种组合的方式就相当于原来继承中的一种实现,这样就有效的减少了实际实现的类的个数。
        从理论上来说,如果用桥接模式的方式来实现这种有两个变化纬度的情况,最后实际的实现类应该是两个纬度上可变数量的和那么多个。同样是上面那个示例,使用桥接模式来实现,实现全的话,最后需要的实现类的数目应该是:3 + 3 = 6个。
        这也从侧面体现了,使用对象组合的方式比继承要来得更灵活。


(8)桥接模式的调用顺序示意图
        桥接模式的调用顺序如图8所示:


                      图8  桥接模式的调用顺序示意图

 

具体代码实例如下

//定义一个事物的抽象,维护对行为实现(Implementor)的引用
public abstract class Shape {
protected Drawing myDrawing;

abstract public void draw();

Shape(Drawing drawing) {
   myDrawing = drawing;
}

public void drawLine() {
   myDrawing.drawLine();
}

public void drawCircle() {
   myDrawing.drawCircle();
}
}

public class Circle extends Shape{
Circle(Drawing drawing) {
   super(drawing);
   // TODO Auto-generated constructor stub
}

@Override
public void draw() {
   // TODO Auto-generated method stub
   myDrawing.drawCircle();
}
}

public class Rectangle extends Shape {
Rectangle(Drawing drawing) {
   super(drawing);
   // TODO Auto-generated constructor stub
}

@Override
public void draw() {
   // TODO Auto-generated method stub
   myDrawing.drawLine();
   myDrawing.drawLine();
   drawLine();
}
}

//实现部分的抽象
public abstract class Drawing {
public abstract void drawLine();
public abstract void drawCircle();
}

public class V1Drawing extends Drawing {
@Override
public void drawCircle() {
   // TODO Auto-generated method stub
   DP1.draw_a_circle();
}

@Override
public void drawLine() {
   // TODO Auto-generated method stub
   DP1.draw_a_line();
}
}

public class V2Drawing extends Drawing{
@Override
public void drawCircle() {
   // TODO Auto-generated method stub
   DP2.draw_a_circle();
}

@Override
public void drawLine() {
   // TODO Auto-generated method stub
   DP2.draw_a_line();
}
}

public class DP1 {
public static void draw_a_line() {
   System.out.println("使用DP1的draw_a_line()画线");
}

public static void draw_a_circle() {
   System.out.println("使用DP1的draw_a_circle()画圆");
}
}

public class DP2 {
public static void draw_a_line() {
   System.out.println("使用DP2的draw_a_line()画线");
}

public static void draw_a_circle() {
   System.out.println("使用DP2的draw_a_circle()画圆");
}
}

//测试类
public class BridgeClient {
public static void main(String args[]) {
   Drawing draw1 = new V1Drawing();
   Drawing draw2 = new V2Drawing();

   Shape shape1 = new Rectangle(draw1);
   shape1.draw();

   Shape shape2 = new Circle(draw2);
   shape2.draw();

   Shape shape3 = new Circle(draw1);
   shape3.draw();
}
}

输出结果:
使用DP1的draw_a_line()画线
使用DP1的draw_a_line()画线
使用DP1的draw_a_line()画线
使用DP2的draw_a_circle()画圆
使用DP1的draw_a_circle()画圆

Bridge模式的优点:
1 分离接口及其实现部分。
2 提高可扩充性。
3 实现细节对客户透明。

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【每天一个java设计模式(八)】 - 桥接模式
【每天一个java设计模式(八)】 - 桥接模式
21 0
Java设计模式--桥接模式
桥接模式(别名:柄体模式) 将抽象部分于它的实现部分分离,使它们都可以独立地变化。 Bridge Pattern(Another Name:Handle-Body) Decouple an abstraction from its implementation so that the two can vary independently. 类图 模式
1629 0
【Java设计模式】——单例模式
单例模式是Java中最简单的设计模式之一,属于创建型模式,它提供一种创建对象的最佳方式。 单例模式顾名思义就是单一的实例,涉及到一个单一的类,该类负责创建自己的对象,同时确保只有一个对象被创建,并且提供一种可以访问这个对象的方式,可以直接访问,不需要实例化该类的对象。 单例模式的特点:单例类只能有一个实例 这个实例必须由单例类自己创建单例类需要提供给外界访问这个实例
26 0
【每天一个java设计模式(三)】 - 单例模式
【每天一个java设计模式(三)】 - 单例模式
20 0
Java 设计模式之单例模式
Java 设计模式之单例模式
65 0
java设计模式---你所不知道的单例模式
单例模式大家都听说过,而且也是项目中最常出现的,但是,我们该如何的去更好的使用单例,如何去保证创建的时候线程安全,如何使得DCL模式不失效问题,如何去避免不必要的资源消耗问题,看到这些前奏,想必大家都会有种往下看的冲动了吧,来看看实现单例的几个关键点: 构造函数不能对外开放 通过一个静态方法或枚举返回单例类对象 确保单例类的对象有且只有一个,尤其是在多线程环境下 确保单例
1614 0
Java设计模式--单例模式
单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 Singleton Pattern Ensure a class only has one instance, and provide a global point of access to it. 类图 模式的结构与使用 单例方法模式的结构中包括一种角色。 + 单件类(Singl
1511 0
JAVA设计模式之单例模式
概念:   java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。   单例模式有一下特点:   1、单例类只能有一个实例。   2、单例类必须自己自己创建自己的唯一实例。
912 0
+关注
聚优云惠
专业科普建站知识 ,让建站变得更简单。专注于WordPress和Java建站知识讲解,云服务器主机知识讲解,建站程序搭建和网站优化。 欢迎访问我的网站 :http://tencent.yundashi168.com
376
文章
310
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载