文章目录示例代码完整代码编译运行什么是适配器模式概念生活类比适配器模式中的三个角色Target目标接口Adaptee被适配者Adapter适配器两种适配器模式类适配器模式 (Class Adapter)对象适配器模式 (Object Adapter)对比示例代码Gitteezhangfen21082/DesignPattern完整代码src/ ├── common/# 共享接口包│ ├── MediaPlayer.java# Target目标接口│ └── AdvancedMediaPlayer.java# Adaptee被适配者接口│ ├── class_adapter/# 类适配器实现│ ├── Mp4Player.java# Adaptee 实现│ ├── MediaAdapter.java# Adapter通过继承实现│ ├── MediaPlayerClient.java# 客户端│ └── ClassAdapterDemo.java# 运行入口│ └── object_adapter/# 对象适配器实现├── Mp4Player.java# Adaptee 实现├── MediaAdapter.java# Adapter通过组合实现├── MediaPlayerClient.java# 客户端└── ObjectAdapterDemo.java# 运行入口编译运行# 编译先编译公共接口再编译实现类javac-dout src/common/*.java javac-dout src/class_adapter/*.java javac-dout src/object_adapter/*.java# 运行类适配器示例java-cpout class_adapter.ClassAdapterDemo# 运行对象适配器示例java-cpout object_adapter.ObjectAdapterDemo什么是适配器模式概念适配器模式是一种结构型设计模式它的核心作用是将一个类的接口转换成客户端期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。简单来说适配器就是在套壳生活类比就像手机充电器的「电源适配器」插座提供 220V 交流电手机需要 5V 直流电适配器的作用就是转换电压让手机能正常充电在代码世界中适配器模式干的是同样的事已有类提供的功能很好但接口不符合你的要求你不想/不能修改原有类适配器来「翻译」让两边能对话适配器模式中的三个角色Target目标接口客户端想要使用的接口。在我们的例子中是MediaPlayer// src/common/MediaPlayer.javapackagecommon;publicinterfaceMediaPlayer{voidplay(Stringfilename);}客户端只认识这个接口它调用play(filename)播放文件。Adaptee被适配者已有的接口功能强大但接口不兼容。在我们的例子中是AdvancedMediaPlayer// src/common/AdvancedMediaPlayer.javapackagecommon;publicinterfaceAdvancedMediaPlayer{voidplayMp4(Stringfilename);voidplayMkv(Stringfilename);}它有playMp4()和playMkv()方法但客户端不认识这些接口。Adapter适配器核心角色负责把「客户端的调用」转换成「被适配者的调用」// src/class_adapter/MediaAdapter.javapackageclass_adapter;importcommon.MediaPlayer;publicclassMediaAdapterextendsMp4PlayerimplementsMediaPlayer{Overridepublicvoidplay(Stringfilename){if(filename.endsWith(.mp4)){playMp4(filename);// 调用被适配者的方法}elseif(filename.endsWith(.mkv)){playMkv(filename);}}}两种适配器模式类适配器模式 (Class Adapter)核心实现通过继承来实现适配器。客户端 --调用--MediaPlayer(Target)↑|implements|MediaAdapter(Adapter)||extends ↓ Mp4Player(Adaptee)关键代码public class MediaAdapter extends Mp4Player implements MediaPlayer// src/class_adapter/MediaAdapter.javapackageclass_adapter;importcommon.MediaPlayer;publicclassMediaAdapterextendsMp4PlayerimplementsMediaPlayer{Overridepublicvoidplay(Stringfilename){if(filename.endsWith(.mp4)){playMp4(filename);// 直接调用父类(Mp4Player)的方法}elseif(filename.endsWith(.mkv)){playMkv(filename);}}// 类适配器优势可以覆盖被适配者的方法OverridepublicvoidplayMp4(Stringfilename){System.out.println(播放前的处理...);super.playMp4(filename);// 调用父类原有逻辑System.out.println(播放后的处理...);}}运行结果客户端请求播放: 复仇者联盟.mp4[ClassAdapter]收到播放请求: 复仇者联盟.mp4 播放前的处理...[Mp4Player]正在播放 MP4 文件: 复仇者联盟.mp4 播放后的处理...对象适配器模式 (Object Adapter)核心实现通过组合/委托来实现适配器。客户端 --调用--MediaPlayer(Target)↑|implements|MediaAdapter(Adapter)||组合 ↓ Mp4Player(Adaptee)关键代码public class MediaAdapter implements MediaPlayerprivate Mp4Player advancedPlayer// src/object_adapter/MediaAdapter.javapackageobject_adapter;importcommon.MediaPlayer;publicclassMediaAdapterimplementsMediaPlayer{privateMp4PlayeradvancedPlayernewMp4Player();Overridepublicvoidplay(Stringfilename){if(filename.endsWith(.mp4)){advancedPlayer.playMp4(filename);// 委托给组合的对象}elseif(filename.endsWith(.mkv)){advancedPlayer.playMkv(filename);}}}运行结果客户端请求播放: 复仇者联盟.mp4[ObjectAdapter]收到播放请求: 复仇者联盟.mp4[Mp4Player]正在播放 MP4 文件: 复仇者联盟.mp4对比特性类适配器对象适配器实现方式extends AdapteeAdaptee adaptee new Adaptee()能否覆盖被适配者方法能通过Override重写不能直接覆盖灵活性较低受限于单继承较高可随时替换被适配者设计原则继承组合优先用类适配器需要在适配时覆盖被适配者的某些方法被适配者类很稳定不会再有子类用对象适配器需要最大灵活性被适配者可能有子类需要适配遵循「优先使用组合而非继承」的设计原则