1. 项目结构
bash
facade-pattern-demo/
├── pom.xml
├── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ ├── Main.java
│ ├── facade/
│ │ ├── ComputerFacade.java
│ │ └── HomeTheaterFacade.java
│ └── subsystems/
│ ├── CPU.java
│ ├── Memory.java
│ ├── HardDrive.java
│ ├── DVDPlayer.java
│ ├── Projector.java
│ ├── SoundSystem.java
│ └── Lights.java
Maven 配置文件 (pom.xml)
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>facade-pattern-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Facade Pattern Demo</name>
<description>Facade Design Pattern Demo Project</description>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 如果需要添加日志或其他依赖,可以在这里添加 -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. 代码实现
-
子系统类-计算机子系统组件
javapackage com.example.subsystems; /** * CPU子系统 */ public class CPU { public void start() { System.out.println("CPU 正在启动..."); System.out.println("CPU 启动完成"); } public void shutdown() { System.out.println("CPU 正在关闭..."); System.out.println("CPU 已关闭"); } public void execute() { System.out.println("CPU 正在执行指令..."); } }javapackage com.example.subsystems; /** * 内存子系统 */ public class Memory { public void load() { System.out.println("内存 正在加载数据..."); System.out.println("内存 数据加载完成"); } public void unload() { System.out.println("内存 正在释放数据..."); System.out.println("内存 数据释放完成"); } }javapackage com.example.subsystems; /** * 硬盘子系统 */ public class HardDrive { public void read() { System.out.println("硬盘 正在读取数据..."); System.out.println("硬盘 数据读取完成"); } public void write() { System.out.println("硬盘 正在写入数据..."); System.out.println("硬盘 数据写入完成"); } } -
子系统类-家庭影院子系统组件
javapackage com.example.subsystems; /** * DVD播放器子系统 */ public class DVDPlayer { public void on() { System.out.println("DVD播放器 已开启"); } public void off() { System.out.println("DVD播放器 已关闭"); } public void play(String movie) { System.out.println("DVD播放器 正在播放电影: " + movie); } public void stop() { System.out.println("DVD播放器 已停止播放"); } public void eject() { System.out.println("DVD播放器 弹出光盘"); } }javapackage com.example.subsystems; /** * 投影仪子系统 */ public class Projector { public void on() { System.out.println("投影仪 已开启"); } public void off() { System.out.println("投影仪 已关闭"); } public void setInput(String input) { System.out.println("投影仪 输入源设置为: " + input); } public void wideScreenMode() { System.out.println("投影仪 设置为宽屏模式"); } }javapackage com.example.subsystems; /** * 音响系统子系统 */ public class SoundSystem { public void on() { System.out.println("音响系统 已开启"); } public void off() { System.out.println("音响系统 已关闭"); } public void setVolume(int level) { System.out.println("音响系统 音量设置为: " + level); } public void setSurroundSound() { System.out.println("音响系统 设置为环绕声模式"); } }javapackage com.example.subsystems; /** * 灯光子系统 */ public class Lights { public void dim(int level) { System.out.println("灯光 调暗至 " + level + "%"); } public void on() { System.out.println("灯光 已开启"); } public void off() { System.out.println("灯光 已关闭"); } } -
外观类-计算机子系统组件
javapackage com.example.subsystems; /** * CPU子系统 */ public class CPU { public void start() { System.out.println("CPU 正在启动..."); System.out.println("CPU 启动完成"); } public void shutdown() { System.out.println("CPU 正在关闭..."); System.out.println("CPU 已关闭"); } public void execute() { System.out.println("CPU 正在执行指令..."); } }javapackage com.example.subsystems; /** * 内存子系统 */ public class Memory { public void load() { System.out.println("内存 正在加载数据..."); System.out.println("内存 数据加载完成"); } public void unload() { System.out.println("内存 正在释放数据..."); System.out.println("内存 数据释放完成"); } }javapackage com.example.subsystems; /** * 硬盘子系统 */ public class HardDrive { public void read() { System.out.println("硬盘 正在读取数据..."); System.out.println("硬盘 数据读取完成"); } public void write() { System.out.println("硬盘 正在写入数据..."); System.out.println("硬盘 数据写入完成"); } } -
外观类-家庭影院子系统组件
javapackage com.example.subsystems; /** * DVD播放器子系统 */ public class DVDPlayer { public void on() { System.out.println("DVD播放器 已开启"); } public void off() { System.out.println("DVD播放器 已关闭"); } public void play(String movie) { System.out.println("DVD播放器 正在播放电影: " + movie); } public void stop() { System.out.println("DVD播放器 已停止播放"); } public void eject() { System.out.println("DVD播放器 弹出光盘"); } }javapackage com.example.subsystems; /** * 投影仪子系统 */ public class Projector { public void on() { System.out.println("投影仪 已开启"); } public void off() { System.out.println("投影仪 已关闭"); } public void setInput(String input) { System.out.println("投影仪 输入源设置为: " + input); } public void wideScreenMode() { System.out.println("投影仪 设置为宽屏模式"); } } ``` ```java package com.example.subsystems; /** * 音响系统子系统 */ public class SoundSystem { public void on() { System.out.println("音响系统 已开启"); } public void off() { System.out.println("音响系统 已关闭"); } public void setVolume(int level) { System.out.println("音响系统 音量设置为: " + level); } public void setSurroundSound() { System.out.println("音响系统 设置为环绕声模式"); } }javapackage com.example.subsystems; /** * 灯光子系统 */ public class Lights { public void dim(int level) { System.out.println("灯光 调暗至 " + level + "%"); } public void on() { System.out.println("灯光 已开启"); } public void off() { System.out.println("灯光 已关闭"); } } -
外观类-计算机外观
javapackage com.example.facade; import com.example.subsystems.CPU; import com.example.subsystems.Memory; import com.example.subsystems.HardDrive; /** * 计算机外观类 - 简化计算机启动和关闭的复杂过程 */ public class ComputerFacade { private CPU cpu; private Memory memory; private HardDrive hardDrive; public ComputerFacade() { this.cpu = new CPU(); this.memory = new Memory(); this.hardDrive = new HardDrive(); } /** * 启动计算机 - 封装了复杂的启动流程 */ public void startComputer() { System.out.println("========== 启动计算机 =========="); cpu.start(); memory.load(); hardDrive.read(); cpu.execute(); System.out.println("计算机启动完成!\n"); } /** * 关闭计算机 - 封装了复杂的关闭流程 */ public void shutdownComputer() { System.out.println("========== 关闭计算机 =========="); cpu.shutdown(); memory.unload(); System.out.println("计算机关闭完成!\n"); } /** * 执行计算任务 - 封装了计算过程 */ public void performCalculation() { System.out.println("========== 执行计算任务 =========="); hardDrive.read(); cpu.execute(); hardDrive.write(); System.out.println("计算任务完成!\n"); } } -
外观类-家庭影院外观
javapackage com.example.facade; import com.example.subsystems.DVDPlayer; import com.example.subsystems.Projector; import com.example.subsystems.SoundSystem; import com.example.subsystems.Lights; /** * 家庭影院外观类 - 简化家庭影院系统的操作 */ public class HomeTheaterFacade { private DVDPlayer dvdPlayer; private Projector projector; private SoundSystem soundSystem; private Lights lights; public HomeTheaterFacade() { this.dvdPlayer = new DVDPlayer(); this.projector = new Projector(); this.soundSystem = new SoundSystem(); this.lights = new Lights(); } /** * 观看电影 - 封装了所有准备工作 */ public void watchMovie(String movie) { System.out.println("========== 准备观看电影 =========="); lights.dim(10); projector.on(); projector.setInput("DVD"); projector.wideScreenMode(); soundSystem.on(); soundSystem.setSurroundSound(); soundSystem.setVolume(20); dvdPlayer.on(); dvdPlayer.play(movie); System.out.println("开始享受电影时光!\n"); } /** * 结束观看电影 - 封装了所有清理工作 */ public void endMovie() { System.out.println("========== 结束观看电影 =========="); dvdPlayer.stop(); dvdPlayer.eject(); dvdPlayer.off(); soundSystem.off(); projector.off(); lights.on(); System.out.println("家庭影院系统已关闭!\n"); } /** * 只听音乐 - 简化操作 */ public void listenToMusic() { System.out.println("========== 准备听音乐 =========="); lights.dim(30); soundSystem.on(); soundSystem.setVolume(15); System.out.println("开始享受音乐!\n"); } /** * 结束听音乐 */ public void endMusic() { System.out.println("========== 结束听音乐 =========="); soundSystem.off(); lights.on(); System.out.println("音乐系统已关闭!\n"); } } -
主程序
javapackage com.example; import com.example.facade.ComputerFacade; import com.example.facade.HomeTheaterFacade; /** * 主程序 - 演示外观模式的使用 */ public class Main { public static void main(String[] args) { System.out.println("========== 外观模式演示 ==========\n"); // 演示计算机外观 System.out.println("1. 计算机系统演示:"); ComputerFacade computer = new ComputerFacade(); computer.startComputer(); computer.performCalculation(); computer.shutdownComputer(); // 演示家庭影院外观 System.out.println("2. 家庭影院系统演示:"); HomeTheaterFacade homeTheater = new HomeTheaterFacade(); homeTheater.watchMovie("阿凡达"); homeTheater.endMovie(); System.out.println("3. 只使用音乐功能演示:"); homeTheater.listenToMusic(); homeTheater.endMusic(); System.out.println("========== 演示结束 =========="); // 演示不使用外观模式的复杂性 System.out.println("\n========== 对比:不使用外观模式 =========="); demonstrateWithoutFacade(); } /** * 演示如果不使用外观模式,客户端需要如何处理复杂的子系统 */ private static void demonstrateWithoutFacade() { System.out.println("不使用外观模式启动家庭影院:"); // 客户端需要直接操作所有子系统 com.example.subsystems.Lights lights = new com.example.subsystems.Lights(); com.example.subsystems.Projector projector = new com.example.subsystems.Projector(); com.example.subsystems.SoundSystem soundSystem = new com.example.subsystems.SoundSystem(); com.example.subsystems.DVDPlayer dvdPlayer = new com.example.subsystems.DVDPlayer(); // 需要按正确顺序调用多个方法 lights.dim(10); projector.on(); projector.setInput("DVD"); projector.wideScreenMode(); soundSystem.on(); soundSystem.setSurroundSound(); soundSystem.setVolume(20); dvdPlayer.on(); dvdPlayer.play("阿凡达"); System.out.println("\n可以看到,不使用外观模式时:"); System.out.println("1. 客户端需要了解所有子系统"); System.out.println("2. 客户端需要知道正确的调用顺序"); System.out.println("3. 客户端代码变得复杂且难以维护"); System.out.println("4. 子系统间的耦合度增加"); } }
3. 构建和运行
-
使用Maven编译:
bashmvn clean compile -
运行主程序:
bashmvn exec:java -Dexec.mainClass="com.example.Main" -
预期输出
bash========== 外观模式演示 ========== 1. 计算机系统演示: ========== 启动计算机 ========== CPU 正在启动... CPU 启动完成 内存 正在加载数据... 内存 数据加载完成 硬盘 正在读取数据... 硬盘 数据读取完成 CPU 正在执行指令... 计算机启动完成! ========== 执行计算任务 ========== 硬盘 正在读取数据... 硬盘 数据读取完成 CPU 正在执行指令... 硬盘 正在写入数据... 硬盘 数据写入完成 计算任务完成! ========== 关闭计算机 ========== CPU 正在关闭... CPU 已关闭 内存 正在释放数据... 内存 数据释放完成 计算机关闭完成! 2. 家庭影院系统演示: ========== 准备观看电影 ========== 灯光 调暗至 10% 投影仪 已开启 投影仪 输入源设置为: DVD 投影仪 设置为宽屏模式 音响系统 已开启 音响系统 设置为环绕声模式 音响系统 音量设置为: 20 DVD播放器 已开启 DVD播放器 正在播放电影: 阿凡达 开始享受电影时光! ========== 结束观看电影 ========== DVD播放器 已停止播放 DVD播放器 弹出光盘 DVD播放器 已关闭 音响系统 已关闭 投影仪 已关闭 灯光 已开启 家庭影院系统已关闭! 3. 只使用音乐功能演示: ========== 准备听音乐 ========== 灯光 调暗至 30% 音响系统 已开启 音响系统 音量设置为: 15 开始享受音乐! ========== 结束听音乐 ========== 音响系统 已关闭 灯光 已开启 音乐系统已关闭! ========== 演示结束 ========== ========== 对比:不使用外观模式 ========== 不使用外观模式启动家庭影院: 灯光 调暗至 10% 投影仪 已开启 投影仪 输入源设置为: DVD 投影仪 设置为宽屏模式 音响系统 已开启 音响系统 设置为环绕声模式 音响系统 音量设置为: 20 DVD播放器 已开启 DVD播放器 正在播放电影: 阿凡达 可以看到,不使用外观模式时: 1. 客户端需要了解所有子系统 2. 客户端需要知道正确的调用顺序 3. 客户端代码变得复杂且难以维护 4. 子系统间的耦合度增加
4. 核心概念
-
外观模式的核心思想:
-
简化接口:为复杂的子系统提供一个统一的简化接口
-
解耦:客户端与子系统之间的解耦
-
封装:隐藏子系统的复杂性
-
-
优点:
-
减少系统间的依赖
-
提高子系统使用的便捷性
-
提高系统的安全性(可以限制对子系统的直接访问)
-
遵循迪米特法则(最少知识原则)
-
-
适用场景:
-
复杂系统需要提供简单入口
-
子系统众多且相互依赖
-
需要层次化系统结构
-
客户端与抽象的实现类之间存在很大的依赖性
-