【HeadFirst系列之HeadFirst设计模式】第8天之适配器模式与外观模式:让不兼容的接口和谐共处!

ops/2025/2/22 18:45:57/

适配器模式外观模式:让不兼容的接口和谐共处!

大家好!今天我们来聊聊设计模式中的适配器模式(Adapter Pattern)和外观模式(Facade Pattern)。如果你曾经遇到过接口不兼容的问题,或者希望简化复杂系统的调用方式,那么这两种模式就是你的救星!本文基于《Head First 设计模式》的适配器模式外观模式章节,通过生动的故事和 Java 代码示例,带你轻松掌握这两种模式的精髓。

在这里插入图片描述


1. 适配器模式:让不兼容的接口和谐共处

故事背景

小明开发了一个音乐播放器系统,系统中有一个 MediaPlayer 接口,用于播放音频文件。现有的实现类 AudioPlayer 可以播放 MP3 文件,但无法播放 MP4 和 VLC 文件。

问题出现

小明希望扩展系统,使其支持播放 MP4 和 VLC 文件。然而,MP4 和 VLC 文件的播放逻辑由第三方库提供,接口与 MediaPlayer 不兼容。

解决方案:适配器模式

小明决定使用适配器模式,将第三方库的接口适配成 MediaPlayer 接口,从而在不修改现有代码的情况下扩展系统功能。

代码实现

1. 定义目标接口
// 目标接口:MediaPlayer
interface MediaPlayer {void play(String audioType, String fileName);
}
2. 实现现有类
// 现有类:AudioPlayer
class AudioPlayer implements MediaPlayer {@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("mp3")) {System.out.println("Playing MP3 file: " + fileName);} else {System.out.println("Unsupported audio type: " + audioType);}}
}
3. 定义第三方接口
// 第三方接口:AdvancedMediaPlayer
interface AdvancedMediaPlayer {void playMp4(String fileName);void playVlc(String fileName);
}// 具体实现类:Mp4Player
class Mp4Player implements AdvancedMediaPlayer {@Overridepublic void playMp4(String fileName) {System.out.println("Playing MP4 file: " + fileName);}@Overridepublic void playVlc(String fileName) {// Do nothing}
}// 具体实现类:VlcPlayer
class VlcPlayer implements AdvancedMediaPlayer {@Overridepublic void playMp4(String fileName) {// Do nothing}@Overridepublic void playVlc(String fileName) {System.out.println("Playing VLC file: " + fileName);}
}
4. 实现适配器
// 适配器类:MediaAdapter
class MediaAdapter implements MediaPlayer {private AdvancedMediaPlayer advancedMediaPlayer;public MediaAdapter(String audioType) {if (audioType.equalsIgnoreCase("vlc")) {advancedMediaPlayer = new VlcPlayer();} else if (audioType.equalsIgnoreCase("mp4")) {advancedMediaPlayer = new Mp4Player();}}@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("vlc")) {advancedMediaPlayer.playVlc(fileName);} else if (audioType.equalsIgnoreCase("mp4")) {advancedMediaPlayer.playMp4(fileName);}}
}
5. 扩展现有类
// 扩展后的 AudioPlayer
class AudioPlayer implements MediaPlayer {private MediaAdapter mediaAdapter;@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("mp3")) {System.out.println("Playing MP3 file: " + fileName);} else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);} else {System.out.println("Unsupported audio type: " + audioType);}}
}
6. 客户端代码
public class MusicPlayerApp {public static void main(String[] args) {MediaPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3", "song.mp3"); // 输出: Playing MP3 file: song.mp3audioPlayer.play("mp4", "movie.mp4"); // 输出: Playing MP4 file: movie.mp4audioPlayer.play("vlc", "video.vlc"); // 输出: Playing VLC file: video.vlcaudioPlayer.play("avi", "video.avi"); // 输出: Unsupported audio type: avi}
}

2. 外观模式:简化复杂系统的调用方式

故事背景

小明开发了一个家庭影院系统,系统中包含多个设备,比如 DVD 播放器投影仪音响等。每次看电影时,小明需要依次打开这些设备,操作非常繁琐。

问题出现

小明希望简化操作,只需调用一个方法就能完成所有设备的准备工作。

解决方案:外观模式

小明决定使用外观模式,将多个设备的操作封装成一个统一的接口,从而简化调用方式。

代码实现

1. 定义子系统类
// DVD 播放器
class DvdPlayer {public void on() {System.out.println("DVD Player is on");}public void play(String movie) {System.out.println("Playing movie: " + movie);}public void off() {System.out.println("DVD Player is off");}
}// 投影仪
class Projector {public void on() {System.out.println("Projector is on");}public void wideScreenMode() {System.out.println("Projector is in widescreen mode");}public void off() {System.out.println("Projector is off");}
}// 音响
class SoundSystem {public void on() {System.out.println("Sound System is on");}public void setVolume(int level) {System.out.println("Sound System volume set to " + level);}public void off() {System.out.println("Sound System is off");}
}
2. 实现外观类
// 外观类:HomeTheaterFacade
class HomeTheaterFacade {private DvdPlayer dvdPlayer;private Projector projector;private SoundSystem soundSystem;public HomeTheaterFacade(DvdPlayer dvdPlayer, Projector projector, SoundSystem soundSystem) {this.dvdPlayer = dvdPlayer;this.projector = projector;this.soundSystem = soundSystem;}public void watchMovie(String movie) {System.out.println("Get ready to watch a movie...");dvdPlayer.on();projector.on();projector.wideScreenMode();soundSystem.on();soundSystem.setVolume(10);dvdPlayer.play(movie);}public void endMovie() {System.out.println("Shutting down the home theater...");dvdPlayer.off();projector.off();soundSystem.off();}
}
3. 客户端代码
public class HomeTheaterApp {public static void main(String[] args) {DvdPlayer dvdPlayer = new DvdPlayer();Projector projector = new Projector();SoundSystem soundSystem = new SoundSystem();HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvdPlayer, projector, soundSystem);homeTheater.watchMovie("Inception"); // 输出: Get ready to watch a movie...homeTheater.endMovie(); // 输出: Shutting down the home theater...}
}

3. 总结

  • 适配器模式:用于解决接口不兼容的问题,通过适配器将不兼容的接口转换为目标接口。
  • 外观模式:用于简化复杂系统的调用方式,通过外观类封装多个子系统的操作。

这两种模式都能帮助我们更好地设计系统,提高代码的可维护性和扩展性。希望本文的讲解和代码示例能帮助你更好地理解适配器模式外观模式


互动话题
你在项目中用过适配器模式外观模式吗?遇到过哪些问题?欢迎在评论区分享你的经验!


http://www.ppmy.cn/ops/160570.html

相关文章

51c大模型~合集69

我自己的原文哦~ https://blog.51cto.com/whaosoft/12221979 #7项基于SAM万物分割模型研究工作 1、CC-SAM: SAM with Cross-feature Attention and Context for Ultrasound Image Segmentation #ECCV2024 #SAM #图像分割 #医学图像 Segment Anything Model (SAM) 在自…

区块链技术前沿:DApp、DeFi与IDO开发的深度探索

随着数字化浪潮的推进,区块链技术作为其核心驱动力之一,正逐步重塑各行各业的面貌。在这一技术浪潮中,DApp(去中心化应用)、DeFi(去中心化金融)以及IDO(首次去中心化交易所发行&…

【Gin】2:快速上手Gin框架(模版、cookie、session)

本文目录 一、模版渲染二、自定义模版函数三、cookie四、Session五、cookie、session区别六、会话攻击 一、模版渲染 在 Gin 框架中,模板主要用于动态生成 HTML 页面,结合 Go 语言的模板引擎功能,实现数据与视图的分离。 模板渲染是一种动态…

去中心化的共同运营平台 方案

实现一个 去中心化的共同运营平台 需要结合技术架构、治理模式和经济模型的设计,同时解决信息真实性、用户激励和去中心化治理的挑战。以下是实现这一目标的路径和关键要素: 一、技术架构设计 1. 去中心化存储与数据管理 区块链底层:使用区…

react(9)-redux

使用CRA快速创建react项目 npx create-react-app react-redux 安装配套工具 npm i reduxjs/toolkit react-redux 启动项目 在创建项目时候会出现一个问题 You are running create-react-app 5.0.0, which is behind the latest release (5.0.1). We no longer support…

从零到一:构建现代 React 应用的完整指南

1. create-react-app (CRA) 简介: create-react-app 是官方推荐的 React 项目脚手架工具,提供了一个开箱即用的开发环境,帮助开发者快速启动 React 应用。它会自动配置 Webpack、Babel、ESLint 等工具,让你专注于开发而不需要手动配置工具链。 特点: 零配置:CRA 自动配…

Apache Spark 的主要特点

Apache Spark 是一个大数据处理框架,提供了快速、通用的数据处理引擎,支持在大规模数据集上进行高效的并行处理。它通过基于内存的计算以及优化的调度来加速数据处理任务,比传统的基于磁盘的数据处理框架(如Hadoop)要快…

Django-Vue 学习-VUE

主组件中有多个Vue组件 是指在Vue.js框架中,主组件是一个父组件,它包含了多个子组件(Vue组件)。这种组件嵌套的方式可以用于构建复杂的前端应用程序,通过拆分功能和视图,使代码更加模块化、可复用和易于维…