持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
桥接模式(Bridge): 在系统沿着多个维度变化的同时,又不增加其复杂度并已达到解耦。
假设有一个已经写好的用户信息页面,现在有个新的需求,给用户信息部分添加一些鼠标划过特效。比如说,用户名在鼠标划过时会改变其背景色,而用户等级、用户消息这种小部件在鼠标划过时则是改变里面的数字的样式。
按照平时的思路,我们会单独给每个元素添加鼠标移入移出事件,像下面这样:
var span = document.getElementsByTagName('span')
// 为用户名绑定特效
span[0].onmouseover = function () {
this.style.color = 'red'
this.style.background = '#ddd'
}
span[0].onmouseout = function () {
this.style.color = 'black'
this.style.background = '#fff'
}
// 为用户等级绑定特效
span[1].onmouseover = function () {
this.getElementsByTagName('strong')[0].style.color = 'red'
this.getElementsByTagName('strong')[0].style.background = '#ddd'
}
span[1].onmouseout = function () {
this.getElementsByTagName('strong')[0].style.color = 'black'
this.getElementsByTagName('strong')[0].style.background = '#fff'
}
这样虽然说实现了需求,但是很显而易见的一个缺陷就是,代码变得十分冗余,有很多代码片段是相似的。假如用户的信息有几十个,那我们就要写非常非常多的重复代码。这个时候,我们就可以使用 桥接模式来解决这种问题了。
在我们编写代码的时候,要 注意对相同逻辑的代码进行抽象提取处理。 比如上面的需求中,当鼠标移入移出时改变的都是元素的字体颜色和背景颜色,我们将这个相似点抽象提取出来,编写一个函数, 让它解除与事件中的this的耦合。
/**
* 抽象函数,改变dom的字体颜色和背景色
* @param {*} dom 要改变样式的dom
* @param {*} color 字体的颜色
* @param {*} bg 背景的颜色
*/
function changeColor(dom, color, bg) {
dom.style.color = color
dom.style.background = bg
}
将相同的逻辑抽象出来之后,我们再来看一看,现在抽象函数有了,元素也有了,我们还需要一个桥梁将元素和抽象函数绑定在一起,而这个桥梁我们称之为 桥接方法, 而通过桥接方法将抽象函数与元素连接起来的这种模式就叫做 桥接模式。
在上面的需求中,我们可以使用一个匿名函数来作为桥接方法,通过这个方法来调用我们的抽象函数。
span[0].onmouseover = function () {
changeColor(this, 'red', '#ddd')
}
span[0].onmouseout = function () {
changeColor(this, 'black', '#fff')
}
// 为用户等级绑定特效
span[1].onmouseover = function () {
changeColor(this.getElementsByTagName('strong')[0], 'red', '#ddd')
}
span[1].onmouseout = function () {
changeColor(this.getElementsByTagName('strong')[0], 'black', '#fff')
}
这样,如果后面再有新的需求,我们就可以直接修改 changColor 的逻辑就可以了,就不用再一个事件一个事件的去重复劳动了。
上面这个例子,演示了桥接模式的 解耦作用,即 先抽象提取共用部分,然后将实现与抽象通过桥接方法连接在一起,进而实现解耦的作用。
多元化对象
桥接模式的强大之处在于 它对于多维的变化也同样适用。
比如说,狗跑步、马跑步、老虎跑步它们跑步这个动作的实质就是位置坐标x,y的变化,我们将这个跑的动作抽象出来,编写一个 run 的抽象函数。然后,我们再创建一个绘制色彩的抽象函数 draw 和一个说话的抽象函数 speak。这些抽象函数创建完成之后,假如我们现在想要创建一个球类,它有颜色且可以运动,那我们只需要将上面的这些抽象函数按需组合在一起就可以了。
小结
桥接模式的主要特点就是 将实现层(如元素绑定事件)和抽象层(相关逻辑)解耦分离,使得两部分可以独立变化。 它与装饰者模式的区别在于,桥接模式侧重的是结构,是对结构的解耦,而装饰者模式侧重的则是封装。