我们先来看一段golang代码,如果它走起来像只鸭子,叫起来像只鸭子,那么它可能是一只包装了鸭子适配器的火鸡。假设缺少鸭子对象,想用一些火鸡对象来冒充,显而易见火鸡的接口不同,需要写个适配器:
package main import ( "fmt" ) func main() { duck := &MallardDuck{} turkey := &WildTurkey{} turkeyAdapter := NewTurkeyAdapter(turkey) fmt.Println("The Turkey says...") turkey.gobble() turkey.fly() fmt.Println("The Duck says...") duck.quack() duck.fly() fmt.Println("The TurkeyAdapter says...") turkeyAdapter.quack() turkeyAdapter.fly() } //鸭子Duck接口,具备呱呱叫和飞行的能力 type Duck interface { quack() //呱呱叫 fly() //飞行 } //火鸡Turkey接口 type Turkey interface { gobble() //火鸡不会呱呱叫,只会咯咯叫(gobble) fly() //火鸡也会飞,虽然飞不远 } //实现了Duck接口 type MallardDuck struct{} func (*MallardDuck) quack() { fmt.Println("Quack...") } func (*MallardDuck) fly() { fmt.Println("I'm flying") } //实现了Turkey接口 type WildTurkey struct{} func (*WildTurkey) gobble() { fmt.Println("Gobble...") } func (*WildTurkey) fly() { fmt.Println("I'm flying a short distance") } //首先,需要实现想转换成的类型接口,也就是 //客户所期望看到的接口 type TurkeyAdapter struct { turkey Turkey } //接着,需要取得适配的对象引用 func NewTurkeyAdapter(turkey Turkey) *TurkeyAdapter { return &TurkeyAdapter{ turkey } } //现在需要实现接口中所有的方法, //quack在类之间的转换很简单,调用gobble就可以。 func (this *TurkeyAdapter) quack() { this.turkey.gobble() } //两个接口都具备了fly方法,火鸡飞行距离短, //要让火鸡和鸭子的飞行能对应,必须连续五次调用火鸡的fly func (this *TurkeyAdapter) fly() { for i := 0; i < 5; i++ { this.turkey.fly() } }
现在我们知道什么是适配器了,再看看各部分之间的关系:
客户使用适配器的过程如下:
2.适配器使用被适配者接口把请求转换成被适配者的一个或者多个调用接口。
3.客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用。
适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
这个适配器模式充满着良好的OO设计原则:使用对象组合,以修改的接口包装被适配者。这种做法还有额外的优点,那就是,被适配者的任何子类,都可以搭配着适配器使用。
实际上,有“两种”适配器:“对象”适配器和“类”适配器。上述所述为“对象”适配器。“类”适配器不是使用组合来适配被适配者,而是继承被适配者和目标类。