> For the complete documentation index, see [llms.txt](https://xyy94813.gitbook.io/x-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xyy94813.gitbook.io/x-note/she-ji-mo-shi/chang-jian-she-ji-mo-shi/adapter.md).

# 适配器模式

使接口不兼容的对象能够相互合作

## 适用场景

* 希望使用某个类，但是接口与其它代码不兼容
* 需要复用这一些类，他们处于同一继承体系，并且她们又有了额外的一些共同方法，但这些共同方法不在同一继承体系

## 优/缺点

优点：

* 单一原则。接口和数据转换代码从主逻辑中分离
* 开闭原则。只要客户端代码通过客户端接口与适配器进行交互，你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器

缺点：

* 代码整体复杂度增加， 因为你需要新增一系列接口和类。有时直接更改服务类使其与其他代码兼容会更简单。

## 对比其他模式

* 桥接模式通常会于开发前期进行设计，使你能够将程序的各个部分独立开来以便开发。另一方面，适配器模式通常在已有程序中使用， 让相互不兼容的类能很好地合作。
* 适配器可以对已有对象的接口进行修改，装饰模式则能在不改变对象接口的前提下强化对象功能。此外，装饰还支持递归组合，适配器则无法实现。
* 适配器能为被封装对象提供不同的接口，代理模式能为对象提供相同的接口，装饰则能为对象提供加强的接口。
* 外观模式为现有对象定义了一个新接口，适配器则会试图运用已有的接口。适配器通常只封装一个对象，外观通常会作用于整个对象子系统上。
* 桥接、 状态模式和策略模式（在某种程度上包括适配器）模式的接口非常相似。实际上，它们都基于组合模式——即将工作委派给其他对象，不过也各自解决了不同的问题。模式并不只是以特定方式组织代码的配方，你还可以使用它们来和其他开发者讨论模式所解决的问题。

## 实现示例

```ts
class RoundHole {
  getRadius() {}
  fits(peg: RoundPge) {
    return this.getRadius() >= pge.getRadius();
  }
}

class RoundPeg {
  getRadius() {}
}

// 不兼容类型
class SquarePeg {
  getWidth(): number {}
}

class SquarePegAdapter extends RoundPeg {
  private peg: SquarePeg;

  constructor(peg: SquarePeg) {
    this.peg = peg;
  }

  getRadius() {
    return (peg.getWidth() * Math.sqrt(2)) / 2;
  }
}
```
