适配器模式定义
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器模式的结构
适配器模式有两种形式:类适配器模式和对象适配器模式
1、类适配器
适配器和适配者是继承关系
Target是客户端期待的接口,Adaptee是需要适配的接口,Adapter就是适配器。
目标角色(Target):客户端期待的接口,因为是类适配器,Adapter和Adaptee是继承关系,因为单继承原因,所以Target必定为接口,不可以是类。
源角色(Adaptee):需要适配的接口,即现在可用的,但是与Target不匹配的接口。
适配器角色(Adapter):链接目标角色和源角色的中间层。必须实现Target接口且继承Adaptee类。从而在客户端中将Adapter替换Target供客户端使用。
理解
适配器类实现了Target接口和继承Adaptee类,从而同时拥有了Target和Adaptee的特性。通过多态,在使用了Target的地方可以替换成Adapter。
interface Target{ void sampleOperate1(); void sampleOperate2(); } class Adaptee{ public void sampleOperate1(){ } } class Adapter extends Adaptee implements Target{ public void sampleOperate2() { } }
很明显,因为继承,Adapter与Adaptee捆绑死了,如果我有其他源角色,必须再加个适配器去继承它。
2、对象适配器
适配器和适配者是组合关系
目标角色(Target):客户端期待的接口,可以是具体或抽象的类或接口。
源角色(Adaptee):需要适配的接口。
适配器角色(Adapter):适配器,将源接口转成目标接口。
理解
Adapter和Adaptee是组合的关系,所以Target可以通过委托Adapter而使用Adaptee的功能。
interface Target1{ void sampleOperate1(); void sampleOperate2(); } class Adaptee1{ public void sampleOperate1(){ } } class Adapter1 implements Target{ private Adaptee1 adaptee1; public Adapter1(Adaptee1 adaptee1){ this.adaptee1 = adaptee1; } public void sampleOperate1() { adaptee1.sampleOperate1(); } public void sampleOperate2() { } }
这里的源对象Adaptee中的方法不一定要与目标对象Target中的相同。类适配器也是一样,只需要将请求转发向Adaptee即可。
适配器模式是将接口不同而功能相同或类似的两个接口加以转换。对象适配器可以把源类和它的子类适配到目标接口。
什么时候使用
看了很多博客,具体应该怎么用,还是有点模糊,目前,我能想出来的地方,也就两点。
1、接口定义的很多的方法,但是有时候我只会使用到其中的一部分,这时候,可以定义一个抽象类去实现这个接口,然后,我们在使用的时候去继承这个抽象类,然后只覆写我们需要的方法。
interface DoSomeThing { void someThing1(); void someThing2(); } abstract class DoSomeAdapter implements DoSomeThing{ public void someThing1() { System.out.println("do something 111111"); } public void someThing2() { System.out.println("do something 222222"); } } class Demo extends DoSomeAdapter{ public void someThing2() { System.out.println("do other something 222222"); } }
接口DoSomeThing有两个方法,如果我们实现这个接口,那么必须要重写这两个方法,但是我可能只会用到其中的一个,另一个压根用不着,如果这个接口有4-5个方法,那么,我这个类就会有很多空的方法,难看吧,所以通过一个抽象类去实现这个接口,然后我们再去继承这个抽象类,就不用在我这个类中重写那么多空方法了。没记错的话,桌面变成中应该有很多这类的adapter。
2、客户端使用的接口与提供服务的接口不匹配切不能修改的情况下
interface Sort{ List<Integer> sort(List<Integer> list); } class SortOperate implements Sort{ public List<Integer> sort(List<Integer> list) { System.out.println("冒泡排序"); return list; } }
本来有这样一个排序接口,你只知道,你只要扔进去一个list,它会排好序然后返回给你,你用的很开新,然后有一天,写接口的同事说,我要该接口,提供更丰富的功能。他想改成这样
interface Sort{ List<Integer> quickSort(List<Integer> list); List<Integer> bubbleSort(List<Integer> list); } class SortOperate implements Sort{ public List<Integer> quickSort(List<Integer> list) { System.out.println("冒泡排序"); return list; } public List<Integer> bubbleSort(List<Integer> list) { System.out.println("冒泡排序"); return list; } }
然后你就吐槽了,改你妹啊,你知道我有多少地方用了这个破接口吗,你帮我改?难道你改接口我就要加班改代码吗?
于是,好吧,做接口的改成这样
interface Sort{ @Deprecated List<Integer> sort(List<Integer> list); List<Integer> quickSort(List<Integer> list); List<Integer> bubbleSort(List<Integer> list); } class SortHelper{ public List<Integer> quickSort(List<Integer> list) { System.out.println("冒泡排序"); return list; } public List<Integer> bubbleSort(List<Integer> list) { System.out.println("冒泡排序"); return list; } } class SortOperate implements Sort{ private static final SortHelper sortHelper = new SortHelper(); public List<Integer> sort(List<Integer> list) { sortHelper.quickSort(list); return list; } public List<Integer> bubbleSort(List<Integer> list) { sortHelper.bubbleSort(list); return list; } public List<Integer> quickSort(List<Integer> list) { sortHelper.quickSort(list); return list; } }
这里的SortOperate就改成了一个适配器
参考:
http://www.cnblogs.com/java-my-life/archive/2012/04/13/2442795.html
http://blog.csdn.net/lovelion/article/details/8624325
《Java与模式》