# 设计模式——桥接模式
桥梁的作用主要就是连接岸的两边。在开发中,桥接模式的作用也是用于连接,只不过它连接的是抽象部分和实现部分。这么说可能很抽象,我们用具体的例子来展示。桥接模式在javascript中应用最广泛的就是事件监听。
<div id="box1">box1</div>
var oBox1 = document.getElementById('box1');
bindEvent(oBox1,'click',getBeerById)
function getBeerById(){
var id = this.id;
asyncRequest('GET','beer.uri?id='+id,function(resp) {
console.log(resp.responseText);
})
}
如上面代码所示,我们定义了一个div
,给id
为box1
的div
绑定了点击事件,事件函数为getBeerById
。其中bindEvend
点击事件为抽象类,getBeerById
为具体实现类。我们可以发现这个就实现类,也就是getBeerById
函数,只能作为事件触发函数,因为它里面的this.id
依赖于点击事件即抽象类。我们没办法对getBeerById
进行单元测试。现在假设我们又新增了一个div
,它根据类名传递参数,代码如下所示:
<div class="box2">box1</div>
var oBox2 = document.getElementsByClassName('box2')[0];
bindEvent(oBox2,'click',getBeerByClassName)
function getBeerByClassName(){
var className = this.className;
asyncRequest('GET','beer.uri?id='+className,function(resp) {
console.log(resp.responseText);
})
}
上面这个事件处理函数getBeerByClassName
,不再是根据id
请求数据了,而是根据className
请求数据。他们之间仅仅是传递参数的区别,根据代码复用和抽象的原则,我们可能会将代码公告部分抽离出来:
function getBeerId(id){
asyncRequest('GET','beer.uri?id='+id,function(resp) {
console.log(resp.responseText);
})
}
将代码公共部分抽离出来后,虽然提高了代码的服用。但是带来了新的问题,由于之前的具体实现是作为事件处理函数,它依赖于抽象类即点击事件。抽象后的代码没办法作为事件处理函数了(因为之前通过this获取id和className,现在是将其作为参数进行封装了),因此为了保证原来的功能,我们需要对代码及性能修改,使用新的事件处理函数。
//抽象类
bindEvent(oBox1,'click',getBeerByIdBridge)
//桥接函数
function getBeerByIdBridge(e){
getBeerById(this.id)
}
//具体类
function getBeerById(id){
asyncRequest('GET','beer.uri?id='+id,function(resp) {
console.log(resp.responseText)
})
}
通过上面的代码,我们可以知道,定义了一个函数getBeerByIdBridge
来作为事件处理函数。但是这个函数并没有实现具体的功能。具体功能的实现在getBeerById
中,也就是说这个函数其实只是点击事件和具体功能之间连接的桥梁。这就是桥接模式,这个函数就是桥接函数。通过上面的代码,我们可以知道桥接模式就是抽象类和具体类之间抽离开来,使得他们能够各自独自变化,而不是互相依赖。
桥接模式的另一个应用:用于连接多个类。
桥接模式不仅能够用来连接抽象和具体实现,而且还能够用于连接多个类,这些多各类实现各部分功能,通过桥接模式实现完整的功能。看具体的代码如下:
//A类
class A {
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
console.log(this.name)
}
}
//B类
class B {
constructor(job,sex){
this.job = job;
this.sex = sex;
}
showJob(){
console.log(this.job)
}
}
//桥接类
class Bridge{
constructor(){
this.w = new A('刘亦菲',30);
this.h = new B('actor','女')
}
}
let bridge = new Bridge();
console.log(bridge)
bridge.w.showName()
如上面代码所示,通过桥接类将类A
和类B
连接起来了,A
类用于记录姓名和年龄,B
类用于记录职业和性别,桥接类用于这些功能的所有的实现,相当于记录一个人的完整信息。这样的话我们进行开发时,可以分别对A类和B类进行单独开发,各部分实现各自的功能,最后再通过桥接类实现完整功能。
# 桥接模式的总结:
桥接模式用于将抽象与其是实现隔离开来,以便二者独立变化。这种模式对于事件驱动的编程非常方便。另外桥接模式还可以用于将多个类连接起来,用于实现一个完整功能。