适配器模式
代理模式、装饰器模式提供的都是跟原始类相同的接口,而适配器提供跟原始类不同的接口。适配器模式是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。
代理模式、装饰器模式、适配器模式实现的方式大同小异,但是目的不太一样
// 适配器模式:这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作
package main
type IAdaptor interface {
f1()
f2()
fc()
}
// 需要被适配的类
type Adaptee struct{}
func NewAdaptee() Adaptee {
return Adaptee{}
}
// 注意原始类,即需要被适配的类方法名为fa,fb,fc,适配器接口是f1,f2,fc,即要给外部暴露的适配方法是f1,f2,fc
func (a Adaptee) fa() {}
func (a Adaptee) fb() {}
func (a Adaptee) fc() {}
// ------------------------------------------------------------------
// 类适配器: 基于继承
type Adaptor struct {
Adaptee
}
func NewAdaptor() *Adaptor {
return &Adaptor{}
}
func (a Adaptor) f1() {
a.fa()
}
func (a Adaptor) f2() {
//...重新实现f2()...
}
// 这里fc()不需要实现,直接继承自 Adaptee,这是跟对象适配器最大的不同点
// ------------------------------------------------------------------
// 对象适配器:基于组合
type AdaptorV2 struct {
adaptee Adaptee // 依赖注入
}
func NewAdaptorV2(adaptee Adaptee) *AdaptorV2 {
return &AdaptorV2{adaptee: adaptee}
}
func (a AdaptorV2) f1() {
a.adaptee.fa()
}
func (a AdaptorV2) f2() {
//...重新实现f2()...
}
func (a AdaptorV2) fc() {
a.adaptee.fc()
}
func main() {
adaptor := NewAdaptor()
demoFunction(adaptor)
adaptee := NewAdaptee()
adaptorV2 := NewAdaptorV2(adaptee)
demoFunction(adaptorV2)
}
func demoFunction(adaptor IAdaptor) {
adaptor.f1()
adaptor.f2()
adaptor.fc()
}
应用场景
适配器模式是一种事后的补救策略,用来补救设计上的缺陷。应用这种模式算是“无奈之举”。如果在设计初期,我们就能规避接口不兼容的问题,那这种模式就无用武之地了。在实际的开发中,什么情况下才会出现接口不兼容呢?通常有下面这 5
种场景:
- 封装有缺陷的接口设计
- 统一多个类的接口设计
- 替换依赖的外部系统
- 兼容老版本接口
- 适配不同格式的数据