结构型模式-适配器模式
什么是适配器模式
适配器是一种结构型设计模式, 它能使接口不兼容的对象能够 相互合作
- 客户端(Client)是包含当前程序业务逻辑的类
- 客户端接口(Client Interface)描述了其他类与客户端代码 合作时必须遵循的协议
- 服务(Service)中有一些功能类(通常来自第三方或遗留系 统)。客户端与其接口不兼容,因此无法直接调用其功能
- 适配器(Adapter)是一个可以同时与客户端和服务交互的 类:它在实现客户端接口的同时封装了服务对象。适配器接 受客户端通过适配器接口发起的调用,并将其转换为适用于 被封装服务对象的调用。
Example
客户端
package main
import "fmt"
type Client struct { }
func (c *Client) InsertLightningConnectorIntoComputer(com Computer) { fmt.Println("Client inserts Lightning connector into computer.") com.InsertIntoLightningPort() }
|
客户端接口
package main
type Computer interface { InsertIntoLightningPort() }
|
服务
package main
import "fmt"
type Mac struct { }
func (m *Mac) InsertIntoLightningPort() { fmt.Println("Lightning connector is plugged into mac machine.") }
|
未知服务a
package main
import "fmt"
type Windows struct{}
func (w *Windows) insertIntoUSBPort() { fmt.Println("USB connector is plugged into windows machine.") }
|
未知服务a适配器
package main
import "fmt"
type WindowsAdapter struct { windowMachine *Windows }
func (w *WindowsAdapter) InsertIntoLightningPort() { fmt.Println("Adapter converts Lightning signal to USB.") w.windowMachine.insertIntoUSBPort() }
|
main
package main
func main() {
client := &Client{} mac := &Mac{}
client.InsertLightningConnectorIntoComputer(mac)
windowsMachine := &Windows{} windowsMachineAdapter := &WindowsAdapter{ windowMachine: windowsMachine, }
client.InsertLightningConnectorIntoComputer(windowsMachineAdapter) }
|
适用场景
- 当你希望使用某个类,但是其接口与其他代码不兼容时,可 以使用适配器类。
- 适配器模式允许你创建一个中间层类,其可作为代码与遗留 类、第三方类或提供怪异接口的类之间的转换器。
- 如果您需要复用这样一些类,他们处于同一个继承体系,并 且他们又有了额外的一些共同的方法,但是这些共同的方法 不是所有在这一继承体系中的子类所具有的共性
- 你可以扩展每个子类,将缺少的功能添加到新的子类中。但 是,你必须在所有新子类中重复添加这些代码,这样会使得 代码有坏味道
优缺点
优点
- _单一职责原则_你可以将接口或数据转换代码从程序主要业 务逻辑中分离
- 开闭原则。只要客户端代码通过客户端接口与适配器进行交 互,你就能在不修改现有客户端代码的情况下在程序中添加 新类型的适配器
缺点
- 代码整体复杂度增加,因为你需要新增一系列接口和类。有 时直接更改服务类使其与其他代码兼容会更简单
与其他模式的关系
- 桥接通常会于开发前期进行设计,使你能够将程序的各个部 分独立开来以便开发。另一方面,适配器通常在已有程序中 使用,让相互不兼容的类能很好地合作
- 适配器可以对已有对象的接口进行修改,装饰则能在不改变 对象接口的前提下强化对象功能。此外,装饰还支持递归组 合,适配器则无法实现
- 适配器能为被封装对象提供不同的接口,代理能为对象提供 相同的接口,装饰则能为对象提供加强的接口
- 外观为现有对象定义了一个新接口,适配器则会试图运用已 有的接口。适配器通常只封装一个对象,外观通常会作用于 整个对象子系统上
- 桥接、状态和策略(在某种程度上包括适配器)模式的接口 非常相似。实际上,它们都基于组合模式——即将工作委派 给其他对象,不过也各自解决了不同的问题。模式并不只是 以特定方式组织代码的配方,你还可以使用它们来和其他开 发者讨论模式所解决的问题