适用场景
一般来说,适配器模式可以看作一种“补偿模式”,用来补救设计上的缺陷。应用这种模式算是“无奈之举”。如果在设计初期,我们就能协调规避接口不兼容的问题,那这种模式就没有应用的机会了。
type ITarget interface {
f1()
f2()
f3()
}
type Adaptee struct {
}
func (a *Adaptee) fa() {
fmt.Println("fa")
}
func (a *Adaptee) fb() {
fmt.Println("fb")
}
func (a *Adaptee) fc() {
fmt.Println("fc")
}
type Adapter struct {
Adaptee
}
func (a *Adapter) f1() {
a.fa()
}
func (a *Adapter) f2() {
a.fb()
}
func (a *Adapter) f3() {
a.fc()
}
func target(t ITarget) {
t.f1()
t.f2()
t.f3()
}
func TestAdapter() {
a := &Adapter{
Adaptee{},
}
target(a)
}
可以看到Adaptee不满足接口的方法,就用Adapter类作为适配器封装一层,内部调用Adaptee方法
还有一种场景统一多个类的接口设计
某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为统一的接口定义。假设我们的系统要对用户输入的文本内容做敏感词过滤,为了提高过滤的召回率,我们引入了多款第三方敏感词过滤系统,依次对用户输入的内容进行过滤,过滤掉尽可能多的敏感词。但是,每个系统提供的过滤接口都是不同的。这就意味着我们没法复用一套逻辑来调用各个系统。这个时候,我们就可以使用适配器模式,将所有系统的接口适配为统一的接口定义,这样我们可以复用调用敏感词过滤的代码
比如原来有3个过滤系统,每个定义的方法都不一样
type ASensitiveWordFilter struct{}
func (a *ASensitiveWordFilter) FilterSexyWord(string) string {
fmt.Println("FilterSexyWord")
return ""
}
func (a *ASensitiveWordFilter) FilterPolicyWord(string) string {
fmt.Println("FilterPolicyWord")
return ""
}
type BSensitiveWordFilter struct{}
func (b *BSensitiveWordFilter) ViolenceWordFilter(string) string {
fmt.Println("ViolenceWordFilter")
return ""
}
func (b *BSensitiveWordFilter) BloodyWordFilter(string) string {
fmt.Println("BloodyWordFilter")
return ""
}
type CSensitiveWordFilter struct{}
func (c *CSensitiveWordFilter) FilterReligion(string) string {
fmt.Println("FilterReligion")
return ""
}
func TestUnAdapter() {
var str string = "i didnt say anything,i just walk away"
a := &ASensitiveWordFilter{}
b := &BSensitiveWordFilter{}
c := &CSensitiveWordFilter{}
filteredStr := a.FilterSexyWord(str)
filteredStr = a.FilterPolicyWord(filteredStr)
filteredStr = b.BloodyWordFilter(filteredStr)
filteredStr = b.ViolenceWordFilter(filteredStr)
filteredStr = c.FilterReligion(filteredStr)
}
可以看到上面方法TestUnAdapter可测试性差,扩展性不好,为了解决问题, 用适配器为每一个过滤系统新建一个类,适配器类实现接口的统一Filter方法,内部调用各个系统的方法,如下所示
type ISensitiveWordFilter interface {
Filter(s string) string
}
type ASensitiveWordFilterAdaptor struct {
base *ASensitiveWordFilter
}
func (a *ASensitiveWordFilterAdaptor) Filter(s string) string {
filtered := a.base.FilterSexyWord(s)
filtered = a.base.FilterPolicyWord(filtered)
return filtered
}
type BSensitiveWordFilterAdaptor struct {
base *BSensitiveWordFilter
}
func (b *BSensitiveWordFilterAdaptor) Filter(s string) string {
filtered := b.base.BloodyWordFilter(s)
filtered = b.base.ViolenceWordFilter(filtered)
return filtered
}
type CSensitiveWordFilterAdaptor struct {
base *CSensitiveWordFilter
}
func (c *CSensitiveWordFilterAdaptor) Filter(s string) string {
filtered := c.base.FilterReligion(s)
return filtered
}
func TestAdapted() {
var str string = "how do you do"
a := &ASensitiveWordFilterAdaptor{
base: &ASensitiveWordFilter{},
}
b := &BSensitiveWordFilterAdaptor{
base: &BSensitiveWordFilter{},
}
c := &CSensitiveWordFilterAdaptor{
base: &CSensitiveWordFilter{},
}
iFilters := make([]ISensitiveWordFilter, 0)
iFilters = append(iFilters, a, b, c)
for _, filter := range iFilters {
str = filter.Filter(str)
}
}
如上面代码所示,分别为3个系统类新建三个对应的XAdaptor类,这些类实现接口ISensitiveWordFilter的Filter方法,每一个XAdaptor类的Filter方法内部调用对应类的过滤方法,这样对外按照接口形式给出,如TestAdapted方法中所示,比较统一