目录
1.概述
1.1 定义
适配器模式(Adapter Pattern)将一个接口转换成客户希望的另一个接口,从而不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
注意:适配器不是在详细设计的时候添加的,而是解决正在服役的项目的问题。
1.2 作用
适配器模式可以将一个类的接口和另一个类的接口匹配起来,使用的前提是不能或不想修改原来的适配者接口(Adaptee)和目标接口(Target)。
适配器就是一种适配中间件,它存在与不匹配的二者之间。用于连接二者,将不匹配变为匹配。
1.3 应用场景
修改一个正常运行的系统的接口,这时候应该考虑使用适配器模式。
案例如下:
目标类 手机充电器:5V的交流电 被适配者类 家用电压:220V 适配器类 电源适配器,将220V家用直流电转换为5V的交流电
2.类图
2.1 类适配器模式类图
2.2 对象适配器模式类图
3.角色
角色如下所示:
1.Target(抽象目标类) 它表示客户端需要使用的特定领域的接口,该接口不能随意改动,如果改动,其子类就要必须实现这个方法。 2.Adapter(适配器类) 它是适配器模式的核心,用于调用另一个接口,它作为一个转换器,对Adapter接口和Target
接口进行适配。
如果是类适配器,Adapter实现了Target接口,并继承了Adaptee类。在实现Target接口的request()
方法时,可以直接调用从Adaptee类继承过来的specifiRequest()方法;
如果是对象适配器,Adapter继承了Target类且与Adaptee是关联关系,即在Adapter中定义了Adaptee
对象,从而可以调用在Adaptee类中已经实现的方法。
3.Adaptee(被适配者类) 用于定义一个已经存在的接口,这个接口需要被适配。 4.Client(客户类) 用于与符合Target接口的对象进行协同。
4.实例
实例说明:现在有一个类,可以实现播放AVI格式的电影,但是不能播放Mp4格式的电影,这时进行适配器模式
4.1 类适配器
目标类:
/** * 目标类:实现播放Mp4格式的影片 * @author Administrator */ public interface PlayMovie { //目前只能播放AVI格式的电影 public void playMovie(); }
适配器类:
/** * 适配器:适配器模式的核心 * @author Administrator */ public class FormatMovie extends PlayMp4 implements PlayMovie{ @Override public void playMovie() { //调用父类的方法 super.playMp4Movie(); } }
被适配者类:
/** * 适配者,提供了播放Mp4影片的功能 * @author Administrator */ public class PlayMp4 { public void playMp4Movie() { System.out.println("播放Mp4格式的电影"); } }
测试类:
public class Test { public static void main(String[] args) { PlayMovie pm = new FormatMovie(); pm.playMovie(); } }
运行结果:
播放Mp4格式的电影
4.2 对象适配器
目标类:
/** * 目标类:实现播放Mp4格式的影片 * @author Administrator */ public interface PlayMovie { //目前只能播放AVI格式的电影 public void playMovie(); }
适配器类:
/** * 适配器:适配器模式的核心 * @author Administrator */ public class FormatMovie implements PlayMovie{ //创建PlayMp4的实例 private PlayMp4 playMp4 = new PlayMp4(); @Override public void playMovie() { //通过PlayMp4的实例调用方法 playMp4.playMp4Movie(); } }
被适配者类:
/** * 适配者,提供了播放Mp4影片的功能 * @author Administrator */ public class PlayMp4 { public void playMp4Movie() { System.out.println("播放Mp4格式的电影"); } }
测试类:
public class Test { public static void main(String[] args) { PlayMovie pm = new FormatMovie(); pm.playMovie(); } }
运行结果:
播放Mp4格式的电影
5.3 类适配器和对象适配器的区分
从上面的实例代码可以看出,类适配器和对象适配器的区别所在。一个是通过继承,从而调用父类被适配者的方法;另一个是通过定义被适配器的对象,从而进行调用方法。
5.优缺点
5.1 优点
1.可以让任何两个没有关联的类一起运行。 2.提高了类的复用 5.2 缺点
1.过多的使用适配器,会让系统非常凌乱,不易整体进行把握。比如:明明看到调用的是A接口,其实内部被适配成了B接口
的实现。
6.案例为枚举Enumeration适配
代码如下所示:
public class EnumIter implements Iterator {//重点1:配器实现目标接口 private Enumeration e;//重点2:适配器持有被适配接口(对象)的引用 public EnumIter(Enumeration e){ this.e = e; } //将对目标对象的调用转发给真正的被适配的对象 public boolean hasNext() { return e.hasMoreElements(); } public Object next() { return e.nextElement(); } public void remove() { } }
使用:
Enumeration parameterNames = req.getParameterNames(); Iterator enumIter = new EnumIter(parameterNames);//这就是需要实现Iterator的原因 while (enumIter.hasNext()) { String s = (String) enumIter.next(); System.out.println(s); }