23种设计模式之【外观模式】-核心原理与 Java实践
文章目录
- 外观模式(Facade Pattern)
- 核心原理
- Java 实践示例
- 外观模式的特点
- 外观模式的应用场景
外观模式(Facade Pattern)
外观模式是 23 种设计模式中的一种结构型模式,其核心思想是为复杂系统中的一组接口提供一个统一的高层接口,使子系统更易于使用。这种模式通过引入一个 “外观类”,封装子系统的复杂性,为客户端提供简单直观的访问入口,从而降低客户端与子系统之间的耦合度。
核心原理
外观角色(Facade):
提供一个统一的接口,封装子系统的复杂交互逻辑
客户端通过外观类访问子系统,无需直接与子系统交互
子系统角色(Subsystem):
由多个相关联的类组成,实现子系统的具体功能
对子系统而言,外观类只是另一个客户端,不影响子系统内部结构
客户端(Client):
通过外观类与子系统交互,无需了解子系统的内部实现
简化了与复杂系统的交互过程
外观模式的核心是 “封装复杂性,提供简化接口”,遵循 “最少知识原则”(迪米特原则),减少客户端需要了解的类和方法数量。
Java 实践示例
以 “家庭影院系统” 为例实现外观模式:
家庭影院包含多个设备(投影仪、音响、播放器、灯光等)
观看电影需要协调多个设备的操作(开投影仪、开音响、关灯光等)
外观类封装这些复杂操作,提供 “一键观影” 的简化接口
package com.example.demo;public class FacadePattern {public static void main(String[] args) {// 创建子系统组件Projector projector = new Projector();SoundSystem soundSystem = new SoundSystem();Player player = new Player();Light light = new Light();// 创建外观类HomeTheaterFacade theaterFacade = new HomeTheaterFacade(projector, soundSystem, player, light);System.out.println("=== 准备观看电影 ===");theaterFacade.watchMovie("星际穿越");System.out.println("\n=== 电影结束 ===");theaterFacade.endMovie();}// 子系统:投影仪public static class Projector {public void on() {System.out.println("投影仪已开启");}public void off() {System.out.println("投影仪已关闭");}public void setInput(String source) {System.out.println("投影仪输入源设置为:" + source);}public void zoomIn() {System.out.println("投影仪画面放大");}}// 子系统:音响系统public static class SoundSystem {public void on() {System.out.println("音响系统已开启");}public void off() {System.out.println("音响系统已关闭");}public void setVolume(int level) {System.out.println("音响音量设置为:" + level);}}// 子系统:播放器public static class Player {public void on() {System.out.println("播放器已开启");}public void off() {System.out.println("播放器已关闭");}public void play(String movie) {System.out.println("正在播放电影:" + movie);}public void stop() {System.out.println("电影播放已停止");}}// 子系统:灯光public static class Light {public void dim(int level) {System.out.println("灯光调暗至:" + level + "%");}public void on() {System.out.println("灯光已打开");}}// 外观类:家庭影院外观public static class HomeTheaterFacade {// 持有子系统组件的引用private Projector projector;private SoundSystem soundSystem;private Player player;private Light light;// 通过构造函数注入子系统组件public HomeTheaterFacade(Projector projector, SoundSystem soundSystem,Player player, Light light) {this.projector = projector;this.soundSystem = soundSystem;this.player = player;this.light = light;}// 封装观看电影的复杂流程public void watchMovie(String movie) {System.out.println("准备观看电影...");light.dim(20); // 调暗灯光projector.on(); // 打开投影仪projector.setInput("播放器"); // 设置输入源projector.zoomIn(); // 放大画面soundSystem.on(); // 打开音响soundSystem.setVolume(8); // 设置音量player.on(); // 打开播放器player.play(movie); // 播放电影}// 封装结束电影的复杂流程public void endMovie() {System.out.println("结束电影...");light.on(); // 打开灯光projector.off(); // 关闭投影仪soundSystem.off(); // 关闭音响player.stop(); // 停止播放player.off(); // 关闭播放器}}//=== 准备观看电影 ===//准备观看电影...//灯光调暗至:20%//投影仪已开启//投影仪输入源设置为:播放器//投影仪画面放大//音响系统已开启//音响音量设置为:8//播放器已开启//正在播放电影:星际穿越////=== 电影结束 ===//结束电影...//灯光已打开//投影仪已关闭//音响系统已关闭//电影播放已停止//播放器已关闭
}
外观模式的特点
优点:
简化接口:为复杂子系统提供简单统一的访问接口,降低使用难度
解耦客户端与子系统:客户端无需了解子系统内部结构,减少耦合
提高灵活性:子系统内部变化时,只需调整外观类,不影响客户端
符合迪米特原则:客户端只需与外观类交互,减少与其他类的通信
缺点:
外观类可能成为 “上帝对象”,承担过多职责
新增子系统功能时,可能需要修改外观类,违反开闭原则
与适配器模式的区别:
外观模式:为复杂系统提供简化接口,不改变原有接口
适配器模式:将一个接口转换为另一个接口,解决接口不兼容问题
外观模式的应用场景
复杂系统简化:
当系统包含多个子模块,且模块间交互复杂时
例如:电商平台的下单流程(涉及库存、支付、物流等子系统)
框架封装:
框架为开发者提供简化接口,隐藏内部实现细节
例如:Spring 的JdbcTemplate封装了复杂的 JDBC 操作
例如:MyBatis 的SqlSession封装了数据库访问的复杂逻辑
遗留系统集成:
为老旧系统提供新的外观接口,便于与新系统集成
避免直接修改遗留系统代码,降低风险
分层架构中的层间交互:
在分层架构中,每层可为上层提供外观接口
例如:服务层为控制层提供外观接口,封装多个 DAO 的交互
外观模式是 “封装复杂性” 的典型实现,在框架设计和系统集成中应用广泛。它通过提供简洁接口,降低了系统的使用门槛,同时隔离了客户端与子系统的直接依赖,提高了系统的可维护性。