JavaScript - 适配器模式

101 阅读3分钟

概念

适配器模式: 将一个类(对象)的接口( 方法或者属性 )转化成另外一个接口,以满足客户需求。使类(对象)之间的接口的不兼容问题得到解决

在生活中也有很多类似的例子,比如有的手机没有3.5耳机插口,所以就需要增加一个转接头来完成适配功能以确保耳机的正常使用,如下图:

image.png

在我们平时开发中如果是我们自己定义的方法,去直接修改代码即可。但是有很多情况我们回去使用第三方的库暴露出来的 api,这个时候我们就没办法去直接修改他的代码,所以我么需要一种来方法来做适配。

适配数据

假设我有一个对象 obj,我需要它能够适配函数 interfaceMethod

var obj = {
    name:"黑黑的脸蛋",
    age:"23",
    address:"China"
}

function interfaceMethod( name,age,address ) {
    // ...
}

但是我们从代码上面来看,interfaceMethod 函数并不能够直接适配 obj 对象,这是我们就需要一个适配器来来达到我们的目的。

function objTointerfaceAdapter( params ) {
    interfaceMethod( params.name, params.age, params.address )
}

// 利用适配器来传递对象
objTointerfaceAdapter( obj )

可见,通过使用适配器,我们既不用改对象结构,又不用改现有的方法,就达到了目的。

浏览器的事件绑定

在不同的浏览器中我们去绑定事件写法是不同的,如果我们只写 addEventLister 去实现事件绑定,那在其他平台中,我们的代码就会抛出异常。我们可以使用适配器的方法,来适配多种浏览器的事件绑定:

function BindEventListerAdapter( ele, event, callback ) {
    // 普通浏览器的事件绑定
    if( ele.addEventLister ) {
        ele.addEventLister( event, callback )
    } 
    // IE 浏览器事件绑定
    else if( ele.attachEvent ) {
        ele.attachEvent( "on" + event, callback )
    } 
    // 其他平台的事件绑定
    else {
        ele[ "on" + event ] = callback
    }
}

适配 Jquery

比如我在我的代码中去实现了 ajax 方法:

ajax({
    // ...
})

但是因为项目需求,我们引入了 Jquery 第三方库,而使用 ajax 方法的时候就会这样:

$.ajax({
    // ...
})

这是两种不同的写法,我们并不能保证我们的代码会一直使用 Jquery,如果有一天我们不去使用这个库的时候,那他的 ajax 方法就不存在了,又用回来了我们自己的 ajax。但是这两种写法无论是需求的改变还是考虑未来,我们都因该去适配它:

var $ = {
    ajax:function(){
        // ...
    }
}

Vue 中的 computed

Vue 中的 computed 就体会了这一思想:

<template>
    <span> {{ reversedMessage }} </span>
</template>

<script>
export default {
    data:() => ({
        message:"Hello"
    }),
    computed:{
        reversedMessage:function() {
            return this.message.split("").reverse().join("")
        }
    }
}
</script>

message 这个属性的值是 Hello,但我想要的是一个倒转的 Hello, 通过computed 中的 reversedMessage 方法, 我们得到了目标 olleh,且没有改变原有的数值。这里的 reversedMessage 就相当于一个适配器。

使用场景

  • 使用一个已经存在的对象,但其方法或属性不符合我们的要求。
  • 统一多个对象的接口
  • 适配不同格式的数据
  • 同时兼容新老版本

总结

在传统的设计模式中,适配器通常解决两个类接口不兼容的问题。然而在 JavaScrit 中使用更广泛,比如适配不同的库,数据格式等等。

JavaScript 中的适配器模式,更多在对象之间,为了对象可用通常我们会把对象拆分并重新包装,这样我们就需要全面了解对象的内部结构。同时适配器也解决了对象之间的耦合度,虽然在适配器中加入了一些代码增加了资源开销,但是这些都是微乎其微的。