适配器模式和门面模式

178 阅读3分钟

适配器模式

先来举两个现实生活中比较常见的例子:

电源适配器

Mac book电池支持的电压是20V,而我们日常生活中的交流电压都是220V,日本和韩国的交流电压是100V,英国和澳大利亚是240V,那这样就有问题了,电压不匹配,电肯定是充不了的,还可能有安全隐患。这时候就需要适配器来兼容,让电脑能在100~240V电压下都能正常工作。

USB转接口

在以前的电脑上,PS2接口是连接鼠标、键盘等其他外部设备的标准接口。随着技术的发展,越来越多的电脑开始放弃了PS2接口,转而仅支持USB接口。但过去生产出来的只拥有PS2接口的鼠标、键盘、游戏手柄等老是设备,就需要一个USB转接口才能继续正常工作,所以才有了PS2-USB适配器的出现。

是什么

适配器模式是一种亡羊补牢的模式。

在程序设计开发之初,是不会用上适配器的,因为在最初的开发过程中,各种接口、API和方法会尽量保持统一。只是随着技术的变迁,今天开发的接口未来不适用于新系统了,那我们就需要把旧的接口进行包装成一个新的接口,使它继续保持生命力。

我们来看段代码:

let googleMap = {
  show: function () {
    console.log('开始加载谷歌地图')
  }
}
let baiduMap = {
  show: function () {
    console.log('开始加载百度地图')
  }
}
let renderMap = function (map) {
  if (map.show instanceof Function) {
    map.show()
  }
}
renderMap(googleMap)
renderMap(baiduMap)

之所以能通过renderMap统一调用是因为两个map都提供了统一的show方法了,而如果谷歌地图提供的不是统一的show方法,而是display方法,则需要适配器进行转换。

let googleMap = {
  display: function () {
    console.log('开始加载谷歌地图')
  }
}
let baiduMap = {
  show: function () {
    console.log('开始加载百度地图')
  }
}
let renderMap = function (map) {
  if (map.show instanceof Function) {
    map.show()
  }
}
let googleMapAdapter = {
   show: function () {
     googleMap.display()
   }
}
renderMap(googleMapAdapter)
renderMap(baiduMap)

我们新增了个googleMapAdapter对象的show方法用来兼容不统一的display方法。这就是适配器模式的作用和主要用法。

门面模式

定义

门面模式,也可以称外观模式,英文全称是Facade Design Pattern。在 GoF 的《设计模式》一书中,门面模式原文是这样定义的:

Provide a unified interface to a set of interfaces in a subsystem. Facade Pattern defines a higher-level interface that makes the subsystem easier to use.

中文翻译:门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用。

应用场景

其实也是一层封装,让接口对外更易用。举个例子:

在我们系统中,有个查询某条件下所有患者列表信息,现在接口给提供了个接口根据条件A进行查询的,一切都很美好。一段时间后,产品提了需求,要根据条件B(也可能是另一维度)进行查询患者,后端组第一反应就是给我新增个接口来查,我是很拒绝的,都是查患者列表,仅某一条件不一样,为啥要新增接口呢,冗余!服务端是分前台,中台的,我们前端调的一般是前台接口,作为前端,希望前台给我的接口别动,接口如果需要新增接口可以在中台加,前台来处理兼容,保证给前端的接口,或者说提供出去的接口要统一,不能东一个接口,西一个接口,并且功能类似,这样对使用方是很不友好的。

两种模式

主要说它们的不同点:

  • 适配器模式核心在于处理不同接口的兼容性问题,让过去的接口还能在现在当下发光发热,把差异化抹平继续提供服务
  • 门面模式主要是给外部提供统一的接口,增强代码的易用性