1.在说适配器模式时我们需要了解什么是结构型模式
(1)结构型模式关注如何将现有类或对象组织在一起形成更加强大的结构.
(2)不同的结构型模式从不同的角度组合类或对象,它们在尽可能满足各种面向对象设计原则的同时为类或对象的组合提供一系列巧妙的解决方案.
2.适配器模式概述
(1)在现实生活中生活用电是220V而笔记本一般需要20V那么这中间就需进行转换(交流电适配器).
(2)在软件开发中也存在不兼容的结构,例如方法不一致这种情也可以引入适配器模式.
(3)适配器模式的定义:将一类的接口换成客户希望的另一个接口.适配器模式让那些接口不兼容的类可以一起工作.
3.适配器模式的UML类图展示:
(1)类适配器:关心类的组合一般只存在继承关系和实现关系.

(2)对象适配器:关心类与对象的组合,通过关联关系,在一个类中定义另一个类的实例对象,然后通过该对象调用相应的方法.

4.典型的类适配器代码展示:
public class Adapter extends Adaptee implements Target {
public void request() {
super.specificRequest();
}
}
public class Adapter extends Target {
private Adaptee adaptee; //维持一个对适配者对象的引用
public Adapter(Adaptee adaptee) {
this.adaptee=adaptee;
}
public void request() {
adaptee.specificRequest(); //转发调用
}
}
5.这里有一个题目方便大家理解
某公司欲开发一款儿童玩具汽车,为了更好地吸引小朋友的注意力,该玩具汽车在移动过程中伴随着灯光闪烁和声音提示。在该公司以往的产品中已经实现了控制灯光闪烁(例如警灯闪烁)和声音提示(例如警笛音效)的程序,为了重用先前的代码并且使得汽车控制软件具有更好的灵活性和扩展性,现使用适配器模式设计该玩具汽车控制软件。
1.UML类图分析:

2.简要介绍各自的职责
实例代码
(1) CarController:汽车控制类,充当目标抽象类
(2) PoliceSound:警笛类,充当适配者
(3) PoliceLamp:警灯类,充当适配者
(4) PoliceCarAdapter:警车适配器,充当适配器
(5) Client:客户端测试类
(6) XMLUtil:工具类
3.代码分享:
package com.rl.adapter;
public abstract class CarController {
public void move() {
System.out.println("玩具汽车移动");
}
//发出声音
public abstract void phonate();
//灯光闪烁
public abstract void twinkle();
}
package com.rl.adapter;
public class PoliceCarAdapter extends CarController {
private PoliceSound policeSound;
private PoliceLamp policeLamp;
public PoliceCarAdapter() {
policeLamp = new PoliceLamp();
policeSound = new PoliceSound();
}
@Override
public void phonate() {
policeSound.alamSound();
}
@Override
public void twinkle() {
policeLamp.alamLamp();
}
}
package com.rl.adapter;
public class PoliceLamp {
public void alamLamp() {
System.out.println("警示灯闪烁");
}
}
package com.rl.adapter;
public class PoliceSound {
public void alamSound() {
System.out.println("发出声音提示");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>com.rl.adapter.PoliceCarAdapter</className>
</config>
package com.rl.adapter;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* 这个工具类是利用config.xml读取事先设置好的全类名来创建对象
*/
public class XMLUtil {
public static Object getBean() {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document;
document = documentBuilder.parse(new File("src//com//rl//adapter//config.xml"));
NodeList nl = document.getElementsByTagName("className");
Node node = nl.item(0).getFirstChild();
String cName = node.getNodeValue();
Class c = Class.forName(cName);
Object obj = c.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.rl.adapter;
public class Client {
public static void main(String[] args) {
CarController car;
car = (CarController) XMLUtil.getBean();
car.move();
car.phonate();
car.twinkle();
}
}
运行结果如下:
玩具汽车移动
发出声音提示
警示灯闪烁
6.适配器的优缺点
(1)优点:
1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构
2.增加了类的透明性和复用性,提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用
3.灵活性和扩展性非常好
4.类适配器模式:置换一些适配者的方法很方便
5.对象适配器模式:可以把多个不同的适配者适配到同一个目标,还可以适配一个适配者的子类
(2)缺点:
1.类适配器模式:(1) 一次最多只能适配一个适配者类,不能同时适配多个适配者;(2) 适配者类不能为最终类;(3) 目标抽象类只能为接口,不能为类
2.对象适配器模式:在适配器中置换适配者类的某些方法比较麻烦