定义
将抽像部分与它的实现部分分离,使它们都可以独立地变化。
理解
抽像与它的实现分离,这并不是说,让抽像类与其派生类分离,这样的分离没有任何意义。实现指的是抽像类和它的派生类用来实现自己的对象。
学习桥接模式关键是要理解抽象部分与实现部分的分离。
用一个例子来说明,比如画一个红色的圆和黄色的三角形。有两种做法,
-
先画好圆,调好红色的颜料直接上色,然后继续画好三角形,调好黄色的颜料直接上色。
-
先调好红色的颜料和黄色的颜料,然后再画圆和三角形,分别进行上色。
那哪一种做法好,肯定是第二种好了,如果用第一种做法,红色的颜料就和圆的图形耦合在一起了。
用代码来描述一下:
class colorshape {
redCircle() {
console.log('red circle')
}
yellowTriangle() {
console.log('yellow triangle')//三角形
}
}
let cs = new colorshape();
cs.redCircle()
cs.yellowTriangle()
我们把颜色当作抽像类,把图形当作颜色抽像类派生出来的具体类,其中圆和三角形就是具体类实现的。
class Color {
constructor(name) {
this.name = name
}
}
class Shape {
constructor(name, color) {
this.name = name
this.color = color
}
draw() {
console.log(`${this.color.name} ${this.name}`)
}
}
let red = new Color('red')
let yellow = new Color('yello')
let circle = new Shape('circle', red)
circle.draw()
let triangle = new Shape('triangle', yellow)
triangle.draw()
应用
创建一个对象桥接addMethod,实现为对象拓展方法的功能。
抽像层
Object.prototype.addMethod = function (name, fn) {
this[name] = fn;
}
实现层
function Coordinate(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
var box = new Coordinate(20, 10, 10);
为对象拓展方法(桥接方法)
box.addMethod("init", function () {
console.log("初始化X轴坐标" + this.x + " , y轴坐标为:" + this.y + " , z轴坐标为:" + this.z);
});
box.addMethod("getCoordinateY", function () {
console.log("y轴坐标为"+this.y);
});
输出
box.init();// 初始化x轴坐标20,y轴坐标为10,z轴坐标为10。
box.getCoordinateY();// y轴坐标为10
在JavaScript中的应用
在JavaScript中没有抽像类的概念,其实可以这么理解桥接模式在在JavaScript中的应用场景。
不同的对象A和B有相同的行为和特征,将这部分行为和特征单独出来,形成一个新的对象C,在构建对象(A,B)时传入对象C,对象(A,B)的行为函数中调用对象C对应的行为函数。
举一个例子,例如对话框和消息提示两种形式的弹窗都有显示和隐藏的功能。我们就可以把创建对话框和消息提示当作一个具体实现部分,把显示和隐藏的功能当作一个抽像部分。然后将两者分离开来,独立实现,最后桥接起来。
class Toast {
constructor(node, animation) {
this.node = node;
this.animation = animation
}
show() {
this.animation.show(this.node)
}
hide() {
this.animation.hide(this.node)
}
}
class Message {
constructor(node, animation) {
this.node = node;
this.animation = animation
}
show() {
this.animation.show(this.node)
}
hide() {
this.animation.hide(this.node)
}
}
class Animation {
constructor() {
}
hide(node) {
console.log(node, ' hide')
}
show(node) {
console.log(node, ' show')
}
}
let animation = new Animation()
let toast = new Toast('div', animation)
toast.show(); //div show
let message = new Message('div', animation)
message.hide() //div hide
优点和缺点
-
桥接模式优点:
把抽象与实现隔离开,有助于独立地管理程序的各组成部分。
-
桥接模式缺点:
每使用一个桥接元素都要增加一次函数调用,这对应用程序的性能会有一些负面影响。提高了系统的复杂程度。如果一个桥接函数被用于连接两个函数,而其中某个函数根本不会在桥接函数之外被调用,那么此时这个桥接函数就不是非要不可的。