什么是适配器模式

我们来看一张图片:
iphone转接口.png

从iphone7 开始,苹果取消了3.5mm耳机接口。那老的耳机就不能在新的手机上使用了,于是就有了Lightning转3.5毫米耳机转接口。这就是我们生活中一个非常典型的适配器模式的应用。
回到我们的程序语言中,当我(耳机)需要调用某个接口(连接iphone)时,发现接口发生了改动(3.5mm口改成了Lightning口),我们又不想修改我们的调用代码(老耳机还需要连接iphone5s的3.5mm接口)。于是我们就绪需要一个Adapter(转接口)来实现我们的功能。

代码示例

  1. // iphone5s
  2. function iphone5s () {
  3. // 插入耳机方法
  4. this.insert = function (interfaceType) {
  5. if (interfaceType == '3.5mm') {
  6. console.log('playing music in 5')
  7. } else {
  8. throw 'interface no match'
  9. }
  10. }
  11. }
  12. // iphone7
  13. function iphone7 () {
  14. // 插入耳机方法
  15. this.insert = function (interfaceType) {
  16. if (interfaceType == 'Lightning') {
  17. console.log('playing music in 7')
  18. } else {
  19. throw 'interface no match'
  20. }
  21. }
  22. }
  23. // 老的3.5mm的耳机
  24. function earphoneOld () {
  25. var type = '3.5mm'
  26. this.insert = function (phoneInstance) {
  27. phoneInstance.insert(type)
  28. }
  29. }
  30. // 转接口1
  31. function Adapter1 (earphone) {
  32. var convertType = function () {
  33. return 'Lightning'
  34. }
  35. var insert = function (phoneInstance) {
  36. phoneInstance.insert(convertType())
  37. }
  38. return {
  39. insert: insert
  40. }
  41. }
  42. var IPHONE5 = new iphone5()
  43. var IPHONE7 = new iphone7()
  44. var EARPHONEOLD = new earphoneOld()
  45. // 老耳机 + iphone5
  46. EARPHONEOLD.insert(IPHONE5) // 'playing music in 5'
  47. EARPHONEOLD.insert(IPHONE7) // Error 'interface no match'
  48. // 添加适配器
  49. Adapter1(EARPHONEOLD).insert(IPHONE7)// 'playing music in 7'

第三方库的适配场景

通常我们在业务代码中使用ajax请求库的时候会在调用端做一套封装

  1. // 通用的Ajax调用方法
  2. var Ajax = function (options) {
  3. // 具体实现
  4. }
  5. // 使用Ajax
  6. Ajax({
  7. url: 'xxx',
  8. type: 'GET',
  9. header: {},
  10. callback: function (data) {}
  11. })

这么做一方面可以在通用Ajax方法中对错误和异常做一些通用处理,另一方面,能勾通过适配器的方式灵活对第三方库进行替换,方便我们做一些潜在的升级工作。

  1. var Ajax = function (o) {
  2. // jquery ajax adapter
  3. var option = Object.assign({}, {
  4. url: o.url,
  5. type: o.type,
  6. success: o.callback,
  7. ... // other options
  8. })
  9. // 使用jquery的ajax
  10. $.ajax(option)
  11. }
  12. // 如果需要移除业务的jquery依赖
  13. var Ajax = function (o) {
  14. // axios ajax adapter
  15. var option = Object.assign({}, {
  16. ... // adpater options
  17. })
  18. // 使用jquery的ajax
  19. axios(option)
  20. }

如此,当需要改动第三方库时,我们只要修改中间层适配器即可,而无需在每一行业务代码调用处进行修复。

其他应用场景

  • 数据格式转换适配
  • 调用参数匹配的适配

    优点

  • 将目标和调用方解耦,通过引入一个适配器来重用现有的调用方,无需修改原有结构。

  • 灵活性、扩展性好,可以通过使用配置文件,很方便的更换适配器,
  • 可以在不修改原有代码的基础上,增加新的适配器,完全复合开闭原则

    缺点

  • 一次最多只能适配一个适配者类,不能同时适配多个适配者。