适配器模式可以将一个类的接口和另一个类的接口匹配起来,而无需修改原来的适配器接口和抽象目标接口类
适配器模式有类适配器和对象适配器两种
适配器模式的结构
**1.Target(目标抽象类):**就是客户所需要的类,它可以是一个抽象类,可以是一个接口,也可以是一个具体类。
**2.Adapter(适配器类):**这个类是适配器模式中的核心,他通过实现Target接口并且继承Adaptee类来使target和adaptee二者产生联系
**3.Adaptee(适配器类):**这个类就是需要被适配的角色,他定义了一个已经存在的接口,这个接口需要被适配,这个角色一般情况下都是一个具体类
Target类
package com.designpatten.adapter.demo01;
public interface Target {
public void request();
}
Adaptee类
package com.designpatten.adapter.demo01;
public class Adaptee {
public void specificRequest(){
System.out.println("我是被适配的类里面的方法");
}
}
类适配器
类适配器的adapter角色是继承了adaptee(需要被适配的类)并且实现了target(客户想要的类)
package com.designpatten.adapter.demo01;
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
super.specificRequest();
}
}
对象适配器
对象适配器的adapter角色内聚了adaptee并且实现了target类
package com.designpatten.adapter.demo01;
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter() {
}
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
下面来看一个小案例
某公司要开发一款儿童玩具车,为了更好地吸引小朋友的注意力,该玩具汽车在移动过程中伴随着灯光闪烁和声音提示。在该公司
以往的产品中已经实现了控制灯光闪烁和声音题是的程序,为了重用先前的代码并且使汽车控制软件具有更好的灵活性和扩展性,
现使用适配器模式设计该玩具汽车控制软件
最后客户需要的类也就是适配器中的target角色
package com.designpatten.adapter.demo02;
/**
* 最终的玩具车的控制类,也就是客户最后所需要的类
*/
public abstract class CarController {
public void move(){
System.out.println("汽车再跑");
}
public abstract void shengying(); //发出声音的方法
public abstract void dengguang(); //发出灯光的方法
}
已经就有了的类,也就是需要被适配的类
package com.designpatten.adapter.demo02;
public class OldLamp {
public void lamp(){
System.out.println("发出灯光");
}
}
package com.designpatten.adapter.demo02;
/**
* 一开始就有的可以发出声音的类
*/
public class OldSound {
public void sound(){
System.out.println("发出声音了");
}
}
适配器类
package com.designpatten.adapter.demo02;
public class CarAdapter extends CarController {
private OldLamp oldLamp;
private OldSound oldSound;
public CarAdapter(OldLamp oldLamp, OldSound oldSound) {
this.oldLamp = oldLamp;
this.oldSound = oldSound;
}
public CarAdapter() {
}
public void setOldLamp(OldLamp oldLamp) {
this.oldLamp = oldLamp;
}
public void setOldSound(OldSound oldSound) {
this.oldSound = oldSound;
}
@Override
public void shengying() {
oldSound.sound();
}
@Override
public void dengguang() {
oldLamp.lamp();
}
}
客户端
package com.designpatten.adapter.demo02;
public class Client {
public static void main(String[] args) {
CarController carController = new CarAdapter(new OldLamp(),new OldSound());
carController.move();
carController.dengguang();
carController.shengying();
}
}
运行结果
这个适配器的类就可以把所有原来就有的类的功能用上,加速了开发
如果需要使用其他声音类或者灯光类,可以增加一个新的适配器类,使用新的适配器来适配新的声音类或者灯光类
适配器模式的优点:
1.将目标类和适配者类解耦了,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构
2.增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端而言是透明的,而且提高了适配者的复用性
3.灵活性和扩展性都非常好,通过使用配置文件可以很方便的更换适配类,也可以在不修改原有代码的基础上增加新的适配器类,完全符合开闭原则
适配器模式缺点:
1.对于像java这种单继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者
2.适配者类不能为最终类,例如在java中不能为final