前言
这是本人的设计模式学习笔记,把自己学习过程中的一些总结和认识记录下来,与诸君共勉。本日为大家带来桥接模式。
基本概念
桥接模式的作用在于将抽象与现实隔离开来,以便二者独立变化。桥接模式可以用于连接公开的API代码和私用的实现代码,此外还可以把多个类联接在一起。举个简单例子。
js
var class1=function(a,b){ this.a=a; this.b=b; }; var class2=function(c,d){ this.c=c; this.d=d; }; var bridge=function(a,b,c,d){ this.one=new class1(a,b); this.two=new class2(c,d); };
进一步解释
桥接模式用途广泛,但把它单独拿出来说把抽象与实现解耦,我们往往摸不着头脑。首先我们还是给出桥接模式的结构示意图:
首先,我们的直觉是要有实现首先是有接口的,实现必定对应于一个接口(目的)。但事实上是实现并不一定绑定在一个接口上,比如一个实现C实现了接口A和接口B中的所有方法,那么它就可以绑定到A或B,我们在使用的时候就不需要为A和B分别构造一个实现了。所以接口和实现是可以组合的,而非绑定死的,这种组合我们称之为桥接模式。
一个对象甚至可以在运行时刻改变它的实现。将Abstraction与Implementor分离有助于降低对实现部分编译时刻的依赖性。另外,接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implementor即可。
上面一番话是理论前提,那么桥接模式到底在做些什么呢?让我们举个例子,现在我们需要来写字,字的大小有三种型号,颜色有5种,一共有15种结果。如果我们使用蜡笔,则必须设计15个不同的蜡笔,但如果我们使用毛笔,毛笔能改变大小,能为它添加不同颜色的染料。我们需要的对象组合一个毛笔对象和一个颜料对象。当然这问题如此建模有点奇怪。让我们看一个更实际点的情形。
你要在不同的操作系统平台上播放不同格式的视频文件,这里有两个变化维度,一是系统平台类型,另一个是视频文件格式,这时创造一个新的对象将原有的两个对象组合起来即可。给出设计的UML图:
所以我们可以看到桥接模式的核心在于组合和变化维度,桥接模式通过组合原有的变化维度得到新对象,新对象实现了原有维度的接口。或者我们这么说,我们通过组合原有的接口的具体实现避免了为原有接口组合产生的新接口重新实现。我的表达有些不准确,但可以看出确实是将接口和实现解耦了。
与其他模式的比较
- 适配器模式是在系统设计完成后用来帮助无关的类协同工作的,而桥接模式则在系统开始设计时就被使用
- 装饰模式把子类超出基类的功能放到单独的类里,桥接模式则把原基类的实现化细节抽象出来构造到一个实现化结构,把原有基类改造成一个抽象化的等级结构,实现在多个维度上德独立变化。我个人的理解就是,不管装饰者模式如何组合,都是行为上的组合,接口依然是原来的接口;而桥接模式的重点是同时利用多个接口来完成新的任务,其组合某种程度上就是接口的组合。
- 抽象工厂可以用来创建和配置特定的桥接模式。
特点
- 分离接口和实现部分
- 提供可扩充性,独立地对抽象和实现两个层次扩充
- 实现细节对用户透明
- 会提供系统复杂度,导致调试更困难
示例
一个比较具体有用的示例是实现xhr请求队列,但代码量相对于一篇博客还是太大了,我就不贴了。有兴趣的同学可以参考这本书《javascript设计模式》第八章第四节。