Adapter Design Pattern

适配器模式(Adapter Design Pattern)是一种结构型设计模式。意图把一个结构的既有接口转换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作的两个结构能够一起工作。 对于这个模式,有一个经常被拿来解释它的例子,就是 USB 转接头充当适配器,把两种不兼容的接口,通过转接变得可以一起工作。

UML Diagram

image

适配器模式也可以称为 Wrapper 模式,通过构建(内嵌一个接口不匹配的 Adaptee)Wrapper 结构来对 Adaptee 进行能力转换以实现 Target 接口。 由于 Client 的业务逻辑依赖的是抽象(Target 接口)而非具体的结构类型,原本无法与 Client 对接的 Adaptee 经过 Adapter 包装也可以与 Client 对接了。

Example

Question:

mac 电脑具备接入 Lightning 插头的能力。
windows 电脑具备接入 USB 插头的能力。
client 希望将 Lightning 插头接入两台电脑,应如何处理?

Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package main

import "fmt"

// 主调方依赖的目标接口
type computer interface {
	insertIntoLightningPort()
}

// 已实现目标接口
type mac struct{}

func (m *mac) insertIntoLightningPort() {
	fmt.Println("Lightning connector is plugged into mac machine.")
}

// 未实现目标接口,待适配
type windows struct{}

func (w *windows) insertIntoUSBPort() {
	fmt.Println("USB connector is plugged into windows machine.")
}

// 适配器
type windowsAdapter struct {
	windowMachine *windows
}

// 适配器通过能力转换(适配),实现目标接口
func (w *windowsAdapter) insertIntoLightningPort() {
	fmt.Println("Adapter converts Lightning signal to USB......")
	w.windowMachine.insertIntoUSBPort()
}

// 主调方
type client struct{}

// 主调方的业务逻辑依赖的是目标接口,而非具体的实现
func (c *client) insertLightningConnectorIntoComputer(com computer) {
	com.insertIntoLightningPort()
}

func main() {
	client := &client{}
	mac := &mac{}

	client.insertLightningConnectorIntoComputer(mac)

	windowsMachine := &windows{}
	windowsMachineAdapter := &windowsAdapter{
		windowMachine: windowsMachine,
	}

	client.insertLightningConnectorIntoComputer(windowsMachineAdapter)
}

Output:

Lightning connector is plugged into mac machine.
Adapter converts Lightning signal to USB......
USB connector is plugged into windows machine.

Application Scenarios

  1. 封装有缺陷的接口设计
  2. 统一多个类的接口设计
  3. 替换依赖的外部系统
  4. 兼容老版本接口
  5. 适配不同格式的数据

References

https://time.geekbang.org/column/article/205912

https://golangbyexample.com/adapter-design-pattern-go/