当前位置: 首页 > news >正文

【设计模式】适配器模式大白话讲解!

适配器模式大白话讲解

一句话概括

就像转接头,让不兼容的东西能够一起工作


现实生活比喻

场景1:电源转接头

  • 问题:中国插头(扁的)插不进欧洲插座(圆的)
  • 解决方案:用一个转接头,中国插头 → 转接头 → 欧洲插座
  • 结果:完美使用!

场景2:翻译官

  • 问题:中国人说中文,美国人说英文,互相听不懂
  • 解决方案:请个翻译,中文 → 翻译 → 英文
  • 结果:顺利沟通!

完整代码示例

场景:让旧式播放器支持新格式

/*** 适配器模式 - 媒体播放器示例*/
public class Main {public static void main(String[] args) {System.out.println("=== 传统MP3播放 ===");MediaPlayer mp3Player = new MP3Player();mp3Player.play("song.mp3");System.out.println("\n=== 通过适配器播放新格式 ===");MediaPlayer advancedPlayer = new MediaAdapter();// 现在可以播放各种格式了!advancedPlayer.play("movie.avi");advancedPlayer.play("video.mp4");advancedPlayer.play("animation.vlc");advancedPlayer.play("music.mp3");}
}/*** 目标接口 - 我们期望的播放器接口*/
interface MediaPlayer {void play(String fileName);
}/*** 已有类 - 只能播放MP3的老式播放器*/
class MP3Player implements MediaPlayer {@Overridepublic void play(String fileName) {if (fileName.endsWith(".mp3")) {System.out.println("播放MP3文件: " + fileName);} else {System.out.println("格式不支持: " + fileName);}}
}/*** 新功能接口 - 高级媒体播放器*/
interface AdvancedMediaPlayer {void playVlc(String fileName);void playMp4(String fileName);void playAvi(String fileName);
}/*** 新功能实现 - 具体的高级播放器*/
class AdvancedPlayer implements AdvancedMediaPlayer {@Overridepublic void playVlc(String fileName) {System.out.println("播放VLC文件: " + fileName);}@Overridepublic void playMp4(String fileName) {System.out.println("播放MP4文件: " + fileName);}@Overridepublic void playAvi(String fileName) {System.out.println("播放AVI文件: " + fileName);}
}/*** 适配器 - 核心!让老播放器支持新格式*/
class MediaAdapter implements MediaPlayer {private AdvancedMediaPlayer advancedPlayer;public MediaAdapter() {this.advancedPlayer = new AdvancedPlayer();}@Overridepublic void play(String fileName) {if (fileName.endsWith(".vlc")) {advancedPlayer.playVlc(fileName);} else if (fileName.endsWith(".mp4")) {advancedPlayer.playMp4(fileName);} else if (fileName.endsWith(".avi")) {advancedPlayer.playAvi(fileName);} else if (fileName.endsWith(".mp3")) {// 适配器也可以直接处理MP3,或者委托给MP3PlayerSystem.out.println("播放MP3文件: " + fileName);} else {System.out.println("格式不支持: " + fileName);}}
}

运行结果

=== 传统MP3播放 ===
播放MP3文件: song.mp3=== 通过适配器播放新格式 ===
播放AVI文件: movie.avi
播放MP4文件: video.mp4
播放VLC文件: animation.vlc
播放MP3文件: music.mp3

更真实的例子:数据库连接适配器

/*** 数据库连接适配器示例*/
public class DatabaseExample {public static void main(String[] args) {// 老系统用的MySQLDatabase mysql = new MySQLDatabase();mysql.connect();mysql.query("SELECT * FROM users");System.out.println("\n=== 系统升级,要支持新数据库 ===");// 新来的MongoDB不兼容老接口Database adapter = new MongoDBAdapter();adapter.connect();adapter.query("db.users.find()");}
}/*** 目标接口 - 老系统期望的数据库接口*/
interface Database {void connect();void query(String sql);
}/*** 已有类 - MySQL数据库*/
class MySQLDatabase implements Database {@Overridepublic void connect() {System.out.println("MySQL连接成功");}@Overridepublic void query(String sql) {System.out.println("执行SQL: " + sql);}
}/*** 需要适配的类 - MongoDB(不兼容的接口)*/
class MongoDB {public void mongoConnect() {System.out.println("MongoDB连接成功");}public void find(String command) {System.out.println("执行Mongo命令: " + command);}
}/*** 适配器 - 让MongoDB看起来像传统数据库*/
class MongoDBAdapter implements Database {private MongoDB mongoDB;public MongoDBAdapter() {this.mongoDB = new MongoDB();}@Overridepublic void connect() {mongoDB.mongoConnect();  // 适配:connect → mongoConnect}@Overridepublic void query(String sql) {// 把SQL转换成MongoDB的查询语法String mongoCommand = convertSQLToMongo(sql);mongoDB.find(mongoCommand);  // 适配:query → find}private String convertSQLToMongo(String sql) {// 简单的转换逻辑(实际中会很复杂)if (sql.startsWith("SELECT")) {return "db." + sql.substring(sql.indexOf("FROM") + 5) + ".find()";}return sql;}
}

适配器模式的三种形式

1. 类适配器(通过继承)

// 通过继承来实现适配(Java中不常用,因为单继承限制)
class ClassAdapter extends AdvancedPlayer implements MediaPlayer {@Overridepublic void play(String fileName) {if (fileName.endsWith(".mp4")) {playMp4(fileName);  // 直接调用父类方法}// ... 其他格式}
}

2. 对象适配器(通过组合,推荐)

// 通过组合来实现适配(更灵活)
class ObjectAdapter implements MediaPlayer {private AdvancedMediaPlayer advancedPlayer;  // 组合public ObjectAdapter() {this.advancedPlayer = new AdvancedPlayer();}@Overridepublic void play(String fileName) {// 委托给advancedPlayerif (fileName.endsWith(".mp4")) {advancedPlayer.playMp4(fileName);}}
}

3. 接口适配器(缺省适配器)

// 当接口方法太多时,提供默认空实现
abstract class MediaAdapter implements MediaPlayer {public void play(String fileName) {}  // 默认空实现public void stop() {}                 // 默认空实现public void pause() {}                // 默认空实现
}// 使用时只需要重写需要的方法
class SimplePlayer extends MediaAdapter {@Overridepublic void play(String fileName) {System.out.println("简单播放: " + fileName);}// 不需要实现stop和pause方法
}

适用场景(大白话版)

适合用适配器的场景:

  1. 系统升级

    // 老系统要接入新组件
    OldSystem system = new OldSystem();
    NewComponent adapter = new Adapter(newComponent);
    system.use(adapter);  // 老系统无感知
    
  2. 第三方库集成

    // 第三方库接口不匹配
    ThirdPartyLib lib = new ThirdPartyLib();
    OurInterface adapter = new LibAdapter(lib);
    ourSystem.use(adapter);
    
  3. 接口不兼容

    // 两个系统接口不同
    SystemA systemA = new SystemA();
    SystemB adapter = new ABAdapter(systemA);
    client.use(adapter);
    

不适合的场景:

  1. 可以直接修改源码的情况
  2. 系统设计阶段,应该直接设计统一接口
  3. 过度设计,如果只是临时用一次,不如直接写兼容代码

优缺点

优点:

  • 解耦:客户端和目标类解耦
  • 复用:可以复用现有的类
  • 灵活:可以适配多个不同的类

缺点:

  • 复杂度:增加了系统的类和对象数量
  • 性能:多了一层调用,有轻微性能损失

总结

适配器模式就是:

  • 中间人,在两个不兼容的接口之间搭桥
  • 翻译官,把一种语言翻译成另一种语言
  • 转接头,让不同的插头和插座能够连接

核心口诀:

接口不兼容,
适配器来帮忙。
旧瓶装新酒,
老树开新花!

就像现实中的:

  • 🔌 电源转接头:让不同国家的电器都能用
  • 💬 翻译软件:让不同语言的人能交流
  • 🔄 数据线转换头:让不同接口的设备能连接
  • 🎮 游戏手柄转换器:让新手柄能在老主机上用

记住:适配器是补救措施,不是首选方案!在系统设计时应该尽量避免需要适配器的情况。

http://www.dtcms.com/a/550933.html

相关文章:

  • 西安公司网站建设哪家专业学做软件的网站
  • 四川酒店网站建设seo的中文意思
  • 泰安本地网站老版建设银行网站
  • 简单炫酷的网站百度竞价网站
  • 定制营销型网站做网站被网监叫去很多次
  • 东莞网站包年优化一站式网站建设平台
  • 网站如何做360优化小程序开发费用一览表
  • 302-Spring AI Alibaba MCP NL2SQL 示例
  • 网站音频播放器代码一个平台怎么推广
  • Rust 过程宏开发入门:元编程的艺术与实践
  • 热 动漫-网站正在建设中-手机版6网站上的字体大小
  • 长沙建网站公司网上商城电商项目
  • 网站的主要功能网站建设分几种编程语言
  • 网站编辑做seo好做吗网络推广的公司
  • 工程化(八股)
  • 百度云搭建网站商城网站的建设方案
  • 网站做电商资质吗西安有没有网站建设和营销的培训
  • 汕头模板自助建站叫别人做网站要注意什么
  • html5网站建设基本流程seo排名查询工具
  • 网站系统管理百度推广培训机构
  • 深圳万齐网站建设2020网络公司排名
  • 好未来披露Q2财报:营收8.61亿美元,净利润1.24亿美元
  • Java基础复习-中-集合
  • 【数据库】约束
  • 黄浦网站设计北京网站改版报价
  • 苏州企业网站制作服务wordpress 看不到主题
  • 心率血氧传感器介绍
  • Rust智能指针的奇妙之旅:从踩坑到顿悟
  • 鹰潭做网站的有什么网站是做平面设计的
  • 网站开发有哪些流程Wordpress 插件开发者