什么是适配器模式

将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)

适配器的定义还是比较简单,相信大家看上面的定义也可以看得懂,简单来说,适配器就是把一个类的使用转化为客户所期望的使用方式,适配使得因接口不兼容而不能在一起工作的类能在一起工作。

举例说明

适配器模式在我们的应用中的使用非常广泛,如果大家没有注意过,那么我在这里为大家举一个生活中的例子。

在这里插入图片描述

像这种插头转换器大家应该都见过吧,国内的充电器插头在国外并不能适用,所以我们需要一个转换器(或者说是适配器)用于匹配国外的插槽。同样的道理应用到我们的程序中,当我们的类(插头)并不能适合用户(插槽)使用的时候,我们就需要一个适配器来匹配这两者之间的关系。

绘制UML类图

针对上面的例子我们来绘制一下UML类图

在这里插入图片描述

这就是JavaScript中的适配器模式的UML类图,这个图可能会与java模式下的类图有一定差距,这是因为我们本课程内容为前端中的设计模式JavaScript代码中,并没有接口这个概念,所以大家不要拿java中的类图来与这个比较。并且学习设计模式,最重要的是理解设计,理解模式,我们这里的代码也好,类图也好,都是为了让大家能够更好地理解原理。

OK,回到我们的UML类图中,在上面的类图中其实主要的就是两个类,Adapter表示我们的适配器,Target表示需要被适配的目标类,当用户去调用目标类的方法的时候 ,适配器需要做的是不改变用户的调用方式,通过适配的方式来获取用户想要的结果。 打个具体的比方,比如说Target -> requrest 方法默认返回德国插槽,而我们需要的是一个中国插槽,用户不需要改变插插槽的方式,而是通过适配器来把德国插槽转变为中国插槽。

明白了,我们的原理逻辑之后,我们来看看一下代码实现。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Adapter {
adap () {
return "中国插槽"
}
}

class Target {
constructor () {
this.adapter = new Adapter();
}

request () {
return "德国插槽" + this.adapter.adap();
}
}

const target = new Target();
console.log(target.request());

我们实现的代码非常简单 , 首先request方法默认返回的是一个德国插槽,我们借用适配器Adapter来把Target做了一层转换,把德国插槽转化为中国插槽。

使用场景

适配器模式的使用场景部分,我们还是以jQuery为例子,这里有一个比较典型的事例,就是jQueryajax请求。我们知道在jQuery中使用ajax进行网络请求,我们应该如何使用?

1
2
3
4
5
6
7
8
$.ajax({
url: '/test',
type: 'POST',
dataType: 'json',
data: {
id: "123"
}
})

这是一个标准的ajax请求方式对吧,那么现在我们的应用觉得不再使用jQuery进行网络请求了,改用现在比较火的axios进行网络请求,那么我们应该怎么办 ? 我们先来看一下axios的标注请求方式。

1
2
3
4
5
6
7
8
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});

这是axios的标注网络请求方式,大家想一下如果要替换为axios那么应该怎么做?通常的做法有两种:

  • 第一种做法就是全局替换,把所有的$.ajax替换为axios。不过这种方式,不用说大家可能也知道,坑比较多,很有可能出现各种各样的问题。
  • 第二种方法就是使用适配器模式,我们通过适配器来把所有的$.ajax转化为axios的网络请求。我们来看一下应该怎么做。

先整理一下思路,我们希望把所有的$.ajax(options)都变为axios(options),那么我们就需要对$.ajax(options)添加一个适配器,通过适配器来把所有的请求转到axios(options)上,所以我们的代码应该是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Adapter {
specificAjax(options) {
axios({
method: options.type,
url: options.url,
data: options.data
});
}
};

$.ajax = function (options) {
const adapter = new Adapter();
adapter.specificAjax(options);
}

$.ajax({
url: '/test',
type: 'POST',
dataType: 'json',
data: {
id: "123"
}
})

这样我们就可以通过适配器adapter来把所有的$.ajax(options)都变为axios(options),并且我们不需要改变以前的任何代码!

总结

OK,进入我们的总结部分。我们应该在什么情况下考虑适配器模式?当我们的旧方法不在能适应我们的需求的时候,我们需要对旧方法进行改变,这时我们就可以考虑使用适配器模式。使用适配器模式不会改变我们旧方法的调用代码,并且可以最大程度的降低耦合度。 所以,如果大家遇到了这样的问题,那么需要首先考虑使用适配器模式。