定义
Adapter Partern: 将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
场景
-
系统需要使用现有的类,而这些类的接口不符合系统的需要。
-
典型场景:集成第三方库、遗留系统代码或外部组件。你不想(或不能)修改别人的代码,但你的系统接口标准又和它们不一样。
-
-
想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的类(包括可能在将来引进的类)一起工作。
-
适配器可以作为一个中间层,将未来可能引入的新组件也适配到现有系统中。
-
-
需要一个统一的输出接口,而输入端的类型不可预知或多样化。
-
例如,一个文件处理器可能需要处理来自磁盘、网络、数据库等各种来源的数据,但它们提供的读取接口各不相同。可以为每种来源创建一个适配器,让处理器用统一的接口读取数据。
-
Java场景
-
Java IO 流
-
InputStreamReader
和OutputStreamWriter
就是经典的适配器。 -
InputStreamReader
将基于字节的InputStream
适配为基于字符的Reader
接口。 -
java.io.InputStreamReader(InputStream in)
// 适配器构造函数,接收一个InputStream -
java.io.OutputStreamWriter(OutputStream out)
// 适配器构造函数,接收一个OutputStream
-
-
Java 集合框架
-
Arrays.asList(T[] a)
方法将一个数组适配成一个List
接口。你不能再添加或删除元素,但可以使用List
的所有其他方法来操作数组元素。
-
-
Java AWT / Swing 事件处理
-
早期常用
WindowAdapter
等适配器类(通常是抽象类,提供空实现)。它们是为了简化事件监听器接口的创建,属于一种“缺省适配器”模式,是适配器模式的一种变体。 -
例如,
MouseAdapter
实现了MouseListener
接口,但所有方法都是空实现。你可以只重写你关心的mouseClicked
方法,而不必实现所有5个方法。
-
-
Spring Framework
-
Spring MVC 中的
HandlerAdapter
是核心组件之一。DispatcherServlet 并不直接处理各种Controller(如@Controller
,HttpRequestHandler
,Controller
接口实现类等),而是通过HandlerAdapter
来调用。不同的Controller由不同的适配器来处理,从而屏蔽了Controller的多样性。
-
代码
// 1. 目标接口 (Target Interface) - 美标插座
interface ISocket {void supplyPower(); // 提供电力
}// 2. 被适配者 (Adaptee) - 中标插头
class ChinesePlug {public void connect() {System.out.println("中国插头已连接,开始供电...");}
}// 3. 适配器 (Adapter) - 转换插头 (对象适配器,使用组合)
class SocketAdapter implements ISocket {// 持有被适配对象的引用private ChinesePlug chinesePlug;public SocketAdapter(ChinesePlug chinesePlug) {this.chinesePlug = chinesePlug;}@Overridepublic void supplyPower() {// 调用被适配对象的方法,进行转换System.out.print("[适配器工作] 将美标接口转换为中标接口 -> ");chinesePlug.connect(); // 本质调用的是被适配的方法}
}// 4. 客户端 (Client)class AdapterPatternDemo {public static void main(String[] args) {// 我有一个中标插头的电器ChinesePlug myPlug = new ChinesePlug();// 我在美国,墙上只有美标插座(ISocket),插不进去// 我买了一个转换插头(适配器)ISocket adapter = new SocketAdapter(myPlug);// 现在我可以把转换插头插到墙上的美标插座了// 客户端始终只和目标接口ISocket打交道adapter.supplyPower();}
}
适配器模式代码