Adapter是常用设计模式之一,通过他可以将一个类的接口转换成客户希望的另外一个接口。
Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
下面我们来看一个例子:
假设定义了下面四个类:
现在一个人来了肚子饿了,于是写了下面代码,并且把吃饭传进去,并且调用eat()方法:
过了一会,他又想喝水了,于是去改代码,这次又把喝水传进去,把eat()方法改为drink()方法:
就这样,要睡觉改成调用sleep(),要方便又改成wc()。
没过多久,他就觉得每次都改代码太麻烦了,于是考虑如何把四件事通用出来,但很快他发现由于前期的设计没有考虑周全,
吃饭、喝水、方便、睡觉 并没有统一抽象出一个 doit() 的方法。于是现在只能分别调用各自的eat() drink()等。
而且更糟糕的是吃饭、喝水、方便、睡觉四个类的代码别处也有调用,还不能改,很苦恼。
解决的办法:
首先定义一个接口:
然后定一个吃饭的适配器类,让他实现接口I ,并实现抽象方法doit(),聚合 "吃饭" ,在doit()中调用 "吃饭" 的eat()方法。
修改 "人" 的代码:
这样在 "人" 这个类中,只要传入适配器1,就可以调用 "吃饭" 的eat()方法了!
其余的按照同样的方法封装出Adapter适配器,这样只要传入不同的Adapter,就会做不同的事,
这里由于有了接口规范,抽象出了doit()方法,
所以以后再也不用改人类的代码了^^
当然适配器也可以使用继承来实现,例如喝水的适配器这样来写:
注意:本例中抽象出的是一个接口,所以适配器2方案可行,但如果是抽象类的情况时,方案2会受java单继承的影响不可使用,所以请优先选用聚合的方式。
最后再介绍一下抽象适配器:
例如有下列接口,如果要直接实现这个接口,一定会非常郁闷,因为实现接口意味着你要来实现所有的方法,即便你不需要这个方法 (> <
使用抽象适配器可以帮助我们避免直接实现接口的苦恼:
有了抽象适配器,我们就不必痛苦的直接实现接口了,而是从抽象适配器继承。
抽象适配器只会强制重写部分抽象方法,而其他方法已经做了空实现,我们可以自己选择哪个方法来重写,所以非常灵活。