结构型-外观模式

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. 代码实现

  1. 子系统类-计算机子系统组件

    java 复制代码
    package 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 正在执行指令...");
        }
    }
    java 复制代码
    package com.example.subsystems;
    
    /**
     * 内存子系统
     */
    public class Memory {
        
        public void load() {
            System.out.println("内存 正在加载数据...");
            System.out.println("内存 数据加载完成");
        }
        
        public void unload() {
            System.out.println("内存 正在释放数据...");
            System.out.println("内存 数据释放完成");
        }
    }
    java 复制代码
    package com.example.subsystems;
    
    /**
     * 硬盘子系统
     */
    public class HardDrive {
        
        public void read() {
            System.out.println("硬盘 正在读取数据...");
            System.out.println("硬盘 数据读取完成");
        }
        
        public void write() {
            System.out.println("硬盘 正在写入数据...");
            System.out.println("硬盘 数据写入完成");
        }
    }
  2. 子系统类-家庭影院子系统组件

    java 复制代码
    package 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播放器 弹出光盘");
        }
    }
    java 复制代码
    package 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("音响系统 设置为环绕声模式");
        }
    }
    java 复制代码
    package 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("灯光 已关闭");
        }
    }
  3. 外观类-计算机子系统组件

    java 复制代码
    package 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 正在执行指令...");
        }
    }
    java 复制代码
    package com.example.subsystems;
    
    /**
     * 内存子系统
     */
    public class Memory {
        
        public void load() {
            System.out.println("内存 正在加载数据...");
            System.out.println("内存 数据加载完成");
        }
        
        public void unload() {
            System.out.println("内存 正在释放数据...");
            System.out.println("内存 数据释放完成");
        }
    }
    java 复制代码
    package com.example.subsystems;
    
    /**
     * 硬盘子系统
     */
    public class HardDrive {
        
        public void read() {
            System.out.println("硬盘 正在读取数据...");
            System.out.println("硬盘 数据读取完成");
        }
        
        public void write() {
            System.out.println("硬盘 正在写入数据...");
            System.out.println("硬盘 数据写入完成");
        }
    }
  4. 外观类-家庭影院子系统组件

    java 复制代码
    package 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播放器 弹出光盘");
        }
    }
    java 复制代码
    package 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("音响系统 设置为环绕声模式");
        }
    }
    java 复制代码
    package 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("灯光 已关闭");
        }
    }
  5. 外观类-计算机外观

    java 复制代码
    package 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");
        }
    }
  6. 外观类-家庭影院外观

    java 复制代码
    package 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");
        }
    }
  7. 主程序

    java 复制代码
    package 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. 构建和运行

  1. 使用Maven编译:

    bash 复制代码
    mvn clean compile
  2. 运行主程序:

    bash 复制代码
    mvn exec:java -Dexec.mainClass="com.example.Main"
  3. 预期输出

    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. 核心概念

  • 外观模式的核心思想:

    • 简化接口:为复杂的子系统提供一个统一的简化接口

    • 解耦:客户端与子系统之间的解耦

    • 封装:隐藏子系统的复杂性

  • 优点:

    • 减少系统间的依赖

    • 提高子系统使用的便捷性

    • 提高系统的安全性(可以限制对子系统的直接访问)

    • 遵循迪米特法则(最少知识原则)

  • 适用场景:

    • 复杂系统需要提供简单入口

    • 子系统众多且相互依赖

    • 需要层次化系统结构

    • 客户端与抽象的实现类之间存在很大的依赖性

相关推荐
明洞日记1 天前
【设计模式手册023】外观模式 - 如何简化复杂系统
java·设计模式·外观模式
老朱佩琪!3 天前
Unity外观模式
unity·游戏引擎·外观模式
__万波__14 天前
二十三种设计模式(十)--外观模式
java·设计模式·外观模式
咨询QQ6882388621 天前
ACO蚁群算法优化KELM核极限学习机(ACO-KELM)回归预测MATLAB代码 代码注释清...
外观模式
老鼠只爱大米1 个月前
Java设计模式之外观模式(Facade)详解
java·设计模式·外观模式·facade·java设计模式
ZHE|张恒1 个月前
设计模式(十)外观模式 — 提供统一入口,简化复杂系统的使用
设计模式·外观模式
小毛驴8501 个月前
软件设计模式-外观模式
外观模式
太过平凡的小蚂蚁2 个月前
外观模式:复杂系统的统一入口
外观模式
Yeniden2 个月前
【设计模式】# 外观模式(Facade)大白话讲解!
java·设计模式·外观模式