适配器模式(Adapter Pattern)

适配器模式目的就是不改变原有系统的基础上保留其提供的服务,向调用者提供新的接口服务,使得原本由于接口不兼容而不能一起工作的类可以一起工作。(简单说就是增加兼容性,复用已经存在的功能)

笔记本电脑的电源变压器就是这个原理,把交流电转换成直流电。或者把英文翻译成中文,都是适配器模式。

又分为2种:

  1. 对象适配器模式
  2. 类适配器模式

适配器虽好,但也不要乱用,如果能在设计阶段就统一就是最好的,适配器模式更像是一种补丁。

推荐使用基于组合的对象适配器模式,因为类适配器模式使用了继承增加了模块之间的耦合度,下面的例子就是对象适配器模式。

假设现在有2种电压:

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
package main

import "fmt"

type power220 struct {
power int
name string
}

func (p power220) output220() {
fmt.Printf("This is %s! power is %d\n", p.name, p.power)
}

type power12 struct {
power int
name string
}

func (p power12) output12() {
fmt.Printf("This is %s! power is %d\n", p.name, p.power)
}

func main() {
p220 := power220{power: 220, name: "power220"}
p220.output220()

p12 := power12{power: 12, name: "power12"}
p12.output12()
}

程序输出如下:

1
2
This is power220! power is 220
This is power12! power is 12

但是实际生活中家庭用电都是220V的,不可能和电厂说”我的电脑需要12V直流电,请给我提供12V直流电服务”,也不可能和笔记本电脑制造商说制造一台适配220V交流电的电脑给你,这种情况就类似上面说的”双方不兼容所以不能直接一起工作,而且没法修改任何一方”。此时适配器就该出厂了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type adapter12 struct {
power220 power220
}

func (a adapter12) output12() {
a.power220.output220()
fmt.Printf("This is adapter12,i will transfer %d to 12", a.power220.power)
}

func main() {
p220 := power220{power: 220, name: "power220"}
a := adapter12{power220: p220}
a.output12()
}

程序输出如下:

1
2
This is power220! power is 220
This is adapter12,i will transfer 220 to 12

适配器模式还是比较好理解的一种设计模式。

使用场景

  1. 软件系统结构需要升级或者扩展,又不想影响原有系统的稳定运行时。
  2. 转换类之间的差别不是太大的时候。(把电源转换成砖头就很难)
  3. 创建一个可以复用的类,该类可以与其他不相干的类或者不可预见的类协同工作时。

对比

  1. 和装饰器模式比,适配器模式主要是弥补接口之间的差异,而装饰器模式则是添加新功能。
  2. 和桥接模式比,桥接模式更注重连接功能部分和实现部分的设计,把实现和接口分开,以便独立的变化。