1、什么是适配器模式?
将一个类的接口转换成客户希望的另一个接口。适配器迷失让那些接口不兼容的类可以一起工作。
2、适配器概述
国家的生活用电的电压是220v,而笔记本电脑、手机等电子设备的工作电压没有那么高,为了使笔记本、手机等设备可以使用220v的生活用电,就需要使用适配器,即充电器或变压器。
在软件开发中有时也存在类似这种不兼容的情况,也可以引入类似电源适配器那样称为适配器的角色来协调这些存在不兼容的结构,这种设计方案称之为适配器模式。
与电源适配器类似,在适配器模式中引入了一个被称为适配器的包装类,而它所包装的对象称之为适配者,即被适配的类。适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。
3、适配器模式结构与实现
3.1、适配器模式结构
①、Target(目标抽象类):目标抽象类定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。
②、Adapter(适配器类):可以调用另一个接口,作为一个转换器,对Adapter和Target进行适配。适配器Adapter是适配器的核心,在类适配器中,它通过实现Target接口并继承Adapter类来使二者产生联系,在对象适配器中,它通过继承Target并关联一个Adapter对象使二者产生联系。
③、Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体的类,包含了客户希望使用的业务的方法,在某些情况下甚至没有适配者类的源代码。
3.2适配器模式的实现
①、类适配器
在类适配器中适配者类Adapter没有request方法,而客户端期待这个方法,但适配者类中实现了specificRequest()方法,该方法提供的实现正是客户端所需要的。为了使客户端能够使用适配者类,提供了一个中间类,即适配器类Adapter,适配器类实现了抽象目标类接口Targer,并继承了适配者类,达到了适配的目的。因为适配器类与适配者类是继承关系,称之为类适配器模式。
package com.xu.factory.adapter; /** * @author admin */ public class Adapter extends Adaptee implements Target{ public void request(){ super.specificRequest(); } } ②、对象适配器
在对象适配器中客户端需要调用request方法,而适配者类Adaptee没有该方法,但是他提供的sepecificRequest()方法却是客户端所需要的。为了使客户端能够使用适配者类,需要提供一个包装类Adapter,即适配器类。这个包装类包装了一个适配者的实例,从而将客户端与适配者衔接起来,在适配器的request()方法中调用适配者的specificRequst()方法。因为适配器类与适配者类是关联关系,称之为对象适配器。
package com.xu.factory.adapter; /** * @author admin */ public class Adapter extends Target { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } public void request() { adaptee.specificRequest(); } }
4、适配器模式应用模式
①实例说明
开发儿童玩具车,实现灯光闪烁和生硬提示,复用之前代码(该功能在之前已经实现)。
package com.xu.factory.adapter; /** * 汽车控制类,充当目标控制类 * @author admin */ public abstract class CarController { public void move(){ System.out.println("玩具汽车移动"); } public abstract void phonate();//发出声音 public abstract void twinkle();//灯光闪烁 }
package com.xu.factory.adapter; /** * 充当适配者类 * * @author admin */ public class PoliceLamp { public void alarmLamp() { System.out.println("发出警笛声"); } }
package com.xu.factory.adapter; /** * 警笛声,充当适配者 * @author admin */ public class PoliceSound { public void alarmSound(){ System.out.println("发出警笛声"); } }
package com.xu.factory.adapter; /** * 警车适配器,充当适配器 * * @author admin */ public class PoliceCarAdapter extends CarController { private PoliceLamp lamp; private PoliceSound sound; public PoliceCarAdapter() { lamp = new PoliceLamp(); sound = new PoliceSound(); } //调用适配器者类PoliceLamp @Override public void phonate() { lamp.alarmLamp(); } //调用适配器者类PoliceSound @Override public void twinkle() { sound.alarmSound(); } }
package com.xu.factory.adapter; /** * @author admin */ public class Client { public static void main(String[] args) { CarController car; car = new PoliceCarAdapter(); car.phonate(); car.twinkle(); car.move(); } }
5、适配器模式的优缺点与适用环境
(1)优点
①、将目标类和适配者解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
②、增加了类的透明性和复用性,将具体的业务实现封装在适配者类中,对于客户端类而言是透明,提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
③、较好灵活性和扩展性
④、将多个不同的适配者适配到同一个目标
(2)适用环境
①系统需要使用一些现有的类,这些类的接口不符合系统的需要
②想创建一个重复使用的类,用于和一些彼此之间没有太大关联的类一起工作。