精读《设计模式 - Adapter 适配器模式》

Adapter(适配器模式)

Adapter(适配器模式)属于结构型模式,别名 wrapper,结构性模式关注的是如何组合类与对象,以得到更大的结构,咱们日常工做大部分时间都在与这种设计模式打交道。前端

意图:将一个类的接口转换成客户但愿的另外一个接口。Adapter 模式使得本来因为接口不兼容而不能在一块儿工做的那些类能够一块儿工做。git

这个设计模式的意图很好懂,就是把接口不兼容问题抹平。注意,也仅仅能解决接口不一致的问题,而不能解决功能不一致的问题。github

举例子

若是看不懂上面的意图介绍,没有关系,设计模式须要在平常工做里用起来,结合例子能够加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。sql

接口转换器

插座的种类不少,咱们都用过许多适配器,将不一样的插头进行转换,能够在不替换插座的状况下正常使用。typescript

USB 接口转换也一样精彩,有将 TypeC 接口转换为 TypeA 的,也有将 TypeA 接口转换为 TypeC 的,支持双向转换。数据库

接口转换器就是咱们在生活中使用到的适配器模式,由于厂商并无生产一个新的插座,咱们也没有由于接口不适配而换一个手机,一切只须要一个接口转换器便可,这就是运用设计模式的收益。设计模式

数据库 ORM

ORM 屏蔽了 SQL 这一层,带来的好处是不须要理解不一样 SQL 语法之间的区别,对于通用功能,ORM 会根据不一样的平台,好比 Postgresql、Mysql 进行 SQL 的转换。微信

对 ORM 来讲,屏蔽不一样平台的差别,就是利用适配器模式作到的。app

API Deprecated

当一个普遍使用的库进行了含有 break change 的升级时,每每要留给开发者足够的时间去升级,而不能升级后就直接挂掉,所以被废弃的 API 要标记为 deprecated,而这种被废弃标记的 API 的实际实现,每每是使用新的 API 替代,这种场景正是使用了适配器模式,将新的 API 适配到旧的 API,实现 API Deprecated。框架

意图解释

上面三个例子都知足下面两个条件:

  1. API 不兼容:由于接口的不一样;数据库 SQL 语法的不一样;框架 API 的不一样。
  2. 但能力已支持:插座都拥有充电或读取能力;不一样的 SQL 都拥有查询数据库能力;新 API 覆盖了旧 API 的能力。

这样就能够经过适配器知足 Adapter 的意图:

意图:将一个类的接口转换成客户但愿的另外一个接口。Adapter 模式使得本来因为接口不兼容而不能在一块儿工做的那些类能够一块儿工做。

结构图

适配器的实现分为继承与组合模式。

下面是名词解释:

  • Adapter 适配器,把 Adeptee 适配成 Target
  • Adaptee 被适配的内容,好比不兼容的接口。
  • Target 适配为的内容,好比须要用的接口。

继承:

适配器继承 Adaptee 并实现 Target,适用场景是 AdapteeTarget 结构相似的状况,由于这样只须要实现部分差别化便可。

组合:

组合的拓展性更强,但工做量更大,若是 TargetAdaptee 结构差别较大,适合用组合模式。

代码例子

下面例子使用 typescript 编写。

继承:

`interface ITarget {
// 标准方式是 hello
hello: () => void
}
class Adaptee {
// 要被适配的类方法叫 sayHello
sayHello() {
console.log('hello')
}
}
// 适配器继承 Adaptee 并实现 ITarget
class Adapter extends Adaptee implements ITarget {
hello() {
// 用 sayHello 对接到 hello
super.sayHello()
}
}`

组合:

`interface ITarget {
// 标准方式是 hello
hello: () => void
}
class Adaptee {
// 要被适配的类方法叫 sayHello
sayHello() {
console.log('hello')
}
}
// 适配器继承 Adaptee 并实现 ITarget
class Adapter implements ITarget {
private adaptee: Adaptee
constructor(adaptee: Adaptee) {
this.adaptee = adaptee
}
hello() {
// 用 adaptee.sayHello 对接到 hello
this.adaptee.sayHello()
}
}`

弊端

使用适配器模式自己就多是个问题,由于一个好的系统内部不该该作任何侨界,模型应该保持一致性。只有在以下状况才考虑使用适配器模式:

  1. 新老系统接替,改形成本很是高。
  2. 三方包适配。
  3. 新旧 API 兼容。
  4. 统一多个类的接口。通常能够结合工厂方法使用。

总结

适配器模式也复合开闭原则,在不对原有对象改造的前提下,构造一个适配器就能完成模块衔接。

适配器模式的实现分为类与对象模式,类模式用继承,对象模式用组合,分别适用于 AdapteeTarget 结构类似与结构差别较大的场景,在任何状况下,组合模式都是灵活性最高的。

最后用一张图归纳一下适配器模式的思惟:

讨论地址是: 精读《设计模式 - Adapter 适配器模式》· Issue #279 · dt-fe/weekly

若是你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

关注 前端精读微信公众号

版权声明:自由转载-非商用-非衍生-保持署名( 创意共享 3.0 许可证

本文使用 mdnice 排版

相关文章
相关标签/搜索