设计模式之适配器模式
定义
适配器模式(Adapter)
是最常用的结构型模式之一,在现实生活中,适配器模式也是处处可见,比如电源插头转换器,它可以让英式的插头工作在中式的插座上。 简单来说,就是 适配器模式让原本因为接口不匹配而无法一起工作的两个类/结构体能够一起工作
。
适配器模式所做的就是将一个接口 Adaptee,通过适配器 Adapter 转换成 Client 所期望的另一个接口 Target 来使用,实现原理也很简单,就是 Adapter 通过实现 Target 接口,并在对应的方法中调用 Adaptee 的接口实现。

典型场景
- 将一个接口 A 转换成用户希望的另外一个接口 B,这样就能使原来不兼容的接口 A 和接口 B 相互协作。
老系统的重构
。在不改变原有接口的情况下,让老接口适配到新的接口。
优缺点
优点
能够使 Adaptee 和 Target 之间解耦。通过引入新的 Adapter 来适配 Target,Adaptee 无须修改,符合开闭原则
。 灵活性好
,能够很方便地通过不同的适配器来适配不同的接口。
缺点
增加代码复杂度。适配器模式需要新增适配器,如果滥用会导致系统的代码复杂度增大。
开闭原则
开闭原则(The Open-Close Principle,OCP)中,“开”指的是 对扩展开放
,“闭”指的是 对修改封闭
。
通俗地讲就是,一个软件系统应该 具备良好的可扩展性
,新增功能应当 通过扩展
的方式实现,而不是在已有的代码基础上修改。
示例
以常见的日志操作为例
假设我们有一个现成的 Logger
接口:
type Logger interface {
Log(message string)
}
我们还有一个现成的 ThirdPartyLogger
,它有一个不同的接口:
type ThirdPartyLogger interface {
LogMessage(msg string)
}
我们想要使用 ThirdPartyLogger 来实现 Logger 接口,可以使用适配器模式来完成。
我们首先 定义一个适配器类型
ThirdPartyLoggerAdapter,该类型包装了 ThirdPartyLogger,并实现了 Logger 接口:
type ThirdPartyLoggerAdapter struct {
logger ThirdPartyLogger
}
func (a *ThirdPartyLoggerAdapter) Log(message string) {
a.logger.LogMessage(message)
}
在上面的代码中,ThirdPartyLoggerAdapter 包装了 ThirdPartyLogger 实例,并实现了 Log 方法,该方法将接收到的消息转发给被包装的 ThirdPartyLogger 实例的 LogMessage 方法。
现在,我们可以使用 ThirdPartyLoggerAdapter 来适配 ThirdPartyLogger 到 Logger 接口:
func main() {
// 创建一个 ThirdPartyLogger 实例
thirdPartyLogger := &MyThirdPartyLogger{}
// 使用适配器创建一个 Logger 实例
logger := &ThirdPartyLoggerAdapter{logger: thirdPartyLogger}
// 使用 Logger 实例记录消息
logger.Log("这是一条消息")
}
在上面的代码中,我们创建了一个 ThirdPartyLogger 实例,并将其包装在 ThirdPartyLoggerAdapter 中,以便将其转换为 Logger 接口。然后,我们使用 Logger 实例来记录消息。
总结
适配器模式可以帮助我们将现有的类与其他类协同工作,从而使得代码更加简洁和易于维护。 在 Go 语言中,适配器模式通常使用接口来实现,通过定义一个适配器类型来包装被适配者类型并实现目标接口。