本文共 3151 字,大约阅读时间需要 10 分钟。
今天对适配器模式进行了复习,虽然网上对于适配器模式的描述铺天盖地的多,典型的例子例如充电器的适配,电源电压的适配等,我这篇文章只是自己学习的过程,有时候很多知识自己不写出来总觉着自己没有真正学会。
《JAVA与模式》一书中说:适配器模式(Adapter):将一个类的接口转换成Client端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。具体说就是把适配的类的函数接口转换成为目标类的函数接口,一个类具有我们需要的某个功能,但是它所暴露的接口却不符合当前类的调用,利用适配器模式使之符合当前规范。精髓就是适配器要实现适配,需要实现最终想要得到的方法所在的接口,例如我们要使Adaptee的specificMethod()转换成Target接口的wantMethod()方法,Adapter需要实现Target接口。
主要分为三类:类的适配器模式、对象的适配器模式。
目标接口(Target):最终用户希望看到的接口,可以是类或者接口。
需要适配的类(Adaptee)角色:需要适配的接口或者类。
适配器(Adaper)角色:类似包装一个需要适配的对象,把需适配的接口转换成目标接口。需要有具体逻辑,这一角色不可以是接口,而必须是具体类(暂时只讨论jdk1.7)。
3.1类适配器模式:
类适配器严格来说在java中不应该出现,因为最早的类适配器是要通过多重继承实现的,java不支持多重继承(实现接口或利用内部类继承模拟多继承),这里我们利用接口实现, Adapter 类既继承了 Adaptee (需要被适配的类,具有所需功能但接口不是我们要调用的),也实现了 Target 接口,在 Client 类中我们可以根据需要选择并创建任一种符合需求的子类,来实现具体功能。
3.2对象适配器,它不是使用多继承或继承再实现的方式,而是使用直接关联,就是适配器内部持有需要被适配类的引用(关联是初始化时需要传入),然后实现目标接口,在目标接口符合规范的方法内调用那个我们需要的需适配的类的功能,此时暴露的就是我们需要的接口了。
Android编程过程中展示数据的ListView,GridView,RecyclerView等都是利用Adapter传输数据,有兴趣的可以去看下源码,我会在以后的Android文章中专门分析android源码中用到的设计模式。
适用场景:
4.1、一些已存在的实现某些功能的类的接口不符合当前系统中使用类的接口,又不希望修改原本的类的接口;
4.2、创建一个可以复用的类,使得该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作;
4.3、在不对每一个都进行子类化以匹配它们的接口的情况下,使用一些已经存在的子类。
4.4、使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能
优点;
1通过适配器,客户端可以调用同一接口,来实现所需功能,可能统一接口下内部的实现不同,因而对客户端来说是透明的,代码更加统一规范简单。
2复用了现存的类,不必修改现存不符合使用接口的类。
3将目标类和需适配的类解耦,适配器类重用现有的需适配的类,而无需修改原有代码。
4一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。(对象适配器特有优点)
缺点:
类适配器的缺点:
对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为接口,不能为类,其使用有一定的局限性,不能将一个适配者类和他的子类同时适配到目标接口。
对象适配器的缺点:
与类适配器模式相比,要想置换适配者类的方法就不容易。
类适配器模式:
package com.ts.adapter;/** * * @author ldx * @category类适配器 * */public classClassAdapterDemo { public static void main(String[] args) { Targettarget1=new ConcreteTarget(); Targettarget2=new Adapter(); target1.wantMethod(); target2.wantMethod(); } } interface Target{ public void wantMethod();} class ConcreteTarget implements Target{ @Override public void wantMethod() { System.out.println("用户想要的接口"); } } class Adaptee{ public void SpecificMethod(){ System.out.println("Adaptee具有的特殊的接口"); }} class Adapter extends Adaptee implements Target{ @Override public void wantMethod() { System.out.println("调用的用户想要的接口,下面执行实际执行的接口"); super.SpecificMethod(); } }
对象适配器示例代码:
/** * * @author ldx * @category对象适配器 * */public classObjectAdapterDemo { public static void main(String[] args) { Targettarget1=new ConcreteTarget(); Targettarget2=new Adapter(new Adaptee()); target1.wantMethod(); target2.wantMethod(); } } interface Target{ public void wantMethod();} class ConcreteTarget implements Target{ @Override public void wantMethod() { System.out.println("用户想要的接口"); } } class Adaptee{ public void SpecificMethod(){ System.out.println("Adaptee具有的特殊的接口"); }} class Adapter implements Target{ private Adaptee adaptee; public Adapter(Adaptee adaptee){ this.adaptee=adaptee; } @Override public void wantMethod() { System.out.println("调用的用户想要的接口,下面执行实际执行的接口"); adaptee.SpecificMethod(); }}