• 外观 ( Facade ) 模式


    外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个简化复杂系统的接口,用于与系统交互。外观模式通过创建一个高级别的接口,将一组相关的子系统接口封装在一起,以提供更简单、更统一的接口给客户端使用。

    外观模式的核心思想是将复杂系统的内部结构隐藏起来,只暴露出一个简化的接口,使客户端可以更容易地与系统交互,而不必了解系统的复杂性。这有助于降低客户端与系统之间的耦合度,并提供了一种更高级别、更易用的界面。

    外观模式是迪米特法则的典型应用

    结构

    以下是外观模式的一些重要组成部分:

    1. 外观(Facade): 外观是外观模式的核心,它是一个包含高级别接口的类或接口。外观通常封装了一个或多个子系统的复杂操作,并为客户端提供了一个简单的入口点。

    2. 子系统(Subsystem): 子系统是复杂系统的各个部分,它们包含了系统的实际实现。外观模式的目标是隐藏子系统的复杂性,因此客户端不需要与子系统的具体类直接交互。

    3. 客户端(Client): 客户端是使用外观模式的部分,它通过外观接口与系统交互,而不需要了解系统内部的复杂细节。

    示例

    以下是一个实现外观模式的示例。在这个示例中,将创建一个音响系统的外观,以封装与音响系统相关的复杂操作。

    首先定义子系统的一些类,包括音响、投影仪和DVD播放器:

    // 子系统类1:音响
    class StereoSystem {
        public void turnOn() {
            System.out.println("音响已打开");
        }
    
        public void turnOff() {
            System.out.println("音响已关闭");
        }
    
        public void setVolume(int volume) {
            System.out.println("音响音量已设置为 " + volume);
        }
    }
    
    // 子系统类2:投影仪
    class Projector {
        public void turnOn() {
            System.out.println("投影仪已打开");
        }
    
        public void turnOff() {
            System.out.println("投影仪已关闭");
        }
    
        public void setInput(String input) {
            System.out.println("投影仪输入源已设置为 " + input);
        }
    }
    
    // 子系统类3:DVD播放器
    class DVDPlayer {
        public void turnOn() {
            System.out.println("DVD播放器已打开");
        }
    
        public void turnOff() {
            System.out.println("DVD播放器已关闭");
        }
    
        public void play(String movie) {
            System.out.println("正在播放电影: " + movie);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    接下来,创建外观类 HomeTheaterFacade,它封装了上述子系统的操作,并提供了一个简化的接口供客户端使用:

    // 外观类
    class HomeTheater {
        private StereoSystem stereoSystem;
        private Projector projector;
        private DVDPlayer dvdPlayer;
    
        public HomeTheater() {
            stereoSystem = new StereoSystem();
            projector = new Projector();
            dvdPlayer = new DVDPlayer();
        }
    
        public void watchMovie(String movie, int volume) {
            System.out.println("准备播放电影...");
            projector.turnOn();
            projector.setInput("DVD");
            stereoSystem.turnOn();
            stereoSystem.setVolume(volume);
            dvdPlayer.turnOn();
            dvdPlayer.play(movie);
        }
    
        public void endMovie() {
            System.out.println("电影结束,正在关闭设备...");
            projector.turnOff();
            stereoSystem.turnOff();
            dvdPlayer.turnOff();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    最后,我们可以在客户端中使用外观模式,而不必直接与子系统的复杂操作交互:

    public class Client {
        public static void main(String[] args) {
            HomeTheater homeTheater = new HomeTheater();
    
            // 观看电影
            homeTheater.watchMovie("Avatar", 20);
    
            // 电影结束
            homeTheater.endMovie();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这个示例中,HomeTheaterFacade 封装了音响、投影仪和DVD播放器的复杂操作,客户端只需要通过外观类的接口来操作整个家庭影院系统。这使得客户端的代码更简单、更易读,同时隐藏了系统的复杂性。

    优点

    外观模式的优点包括:

    1. 简化客户端代码: 外观模式提供了一个简化的接口,客户端不需要了解系统内部的复杂结构和交互方式,从而减少了客户端代码的复杂性。
    2. 降低耦合度: 外观模式将客户端与子系统之间的耦合度降低到最低限度。客户端只需要与外观类交互,而不需要直接与多个子系统的类交互,这使得系统更易维护和扩展。
    3. 提供统一的接口: 外观模式为整个子系统提供了一个统一的高级别接口,客户端可以使用这个接口来访问系统的功能,而不必关心每个子系统的详细操作。
    4. 隐藏实现细节: 外观模式隐藏了子系统的复杂性和实现细节,使客户端不需要了解这些细节,从而提高了系统的安全性和可维护性。
    5. 促进松耦合: 外观模式有助于实现松耦合,因为它将系统的不同部分分离开来。这使得系统的不同模块更容易独立开发、测试和维护。

    缺点

    1. 不适用于所有情况: 外观模式并不适用于所有系统。在某些情况下,如果系统的复杂性较低或不需要提供统一的接口,使用外观模式可能会显得过于繁琐。
    2. 可能导致滥用: 如果不谨慎使用外观模式,可能会导致外观类变得过于庞大,承担了过多的职责,从而违反了单一职责原则。同时也不符合开闭原则,修改会非常麻烦。
    3. 增加了一个额外的抽象层次: 外观模式引入了一个额外的抽象层次,这可能会导致一些性能损失,尤其在需要频繁调用外观方法的情况下。

    外观模式常见的应用场景包括:

    • 当系统具有复杂的子系统结构,而客户端只关心与系统的高级别接口交互时,可以使用外观模式。
    • 在大型应用程序中,外观模式可以帮助管理复杂性,并提供更清晰的接口给不同的模块或团队。
    • 在设计新版本或重构现有系统时,外观模式可以用于逐步替代旧的接口,以保持向后兼容性。
    • 在构建库或框架时,外观模式可以为客户端提供一个简化的接口,以便更容易使用库或框架的功能。

    源码解析

    在JDBC中,java.sql.DriverManager 类可以看作是一个外观类,封装了底层数据库驱动程序的加载和数据库连接管理,使开发者能够更轻松地与各种数据库交互。

    以下是一个简单的示例,演示了如何使用java.sql.DriverManager 来建立数据库连接和执行SQL查询:

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class JDBCFacadeExample {
        public static void main(String[] args) {
            // JDBC数据库连接信息
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "123456";
    
            try {
                // 加载数据库驱动程序(这部分由DriverManager处理)
                Class.forName("com.mysql.cj.jdbc.Driver");
    
                // 建立数据库连接(也由DriverManager处理)
                Connection connection = DriverManager.getConnection(url, user, password);
    
                // 创建SQL语句
                String sql = "SELECT * FROM employees";
    
                // 创建并执行SQL查询
                Statement statement = connection.createStatement();
                ResultSet resultSet = statement.executeQuery(sql);
    
                // 处理查询结果
                while (resultSet.next()) {
                    int id = resultSet.getInt("id");
                    String name = resultSet.getString("name");
                    double salary = resultSet.getDouble("salary");
    
                    System.out.println("Employee ID: " + id);
                    System.out.println("Name: " + name);
                    System.out.println("Salary: " + salary);
                }
    
                // 关闭资源(连接、语句和结果集)
                resultSet.close();
                statement.close();
                connection.close();
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    在上述示例中,JDBC的子系统包括以下组成部分:

    1. 数据库驱动程序加载: 这是JDBC的底层组件之一。不同的数据库供应商(如MySQL、Oracle、PostgreSQL等)提供了各自的JDBC驱动程序,用于与其数据库进行通信。加载适当的数据库驱动程序是与特定数据库建立连接的第一步。
    2. 数据库连接管理: 数据库连接是与数据库进行交互的关键组件。JDBC通过java.sql.Connection 接口来表示数据库连接。连接管理包括连接的创建、关闭、连接池管理等任务。这是JDBC底层的复杂性之一。
    3. SQL查询执行: 一旦建立了数据库连接,就可以创建SQL查询并执行它们。这涉及到创建java.sql.Statement 对象或java.sql.PreparedStatement 对象,以及执行查询、更新或批处理操作。SQL查询的执行是与数据库交互的核心任务。
    4. 结果集处理: 查询执行后,JDBC返回一个java.sql.ResultSet 对象,其中包含查询结果集。开发者需要遍历结果集并提取数据以供应用程序使用。结果集处理是另一个重要的子系统。

    java.sql.DriverManager 类充当了外观,封装了底层的数据库驱动程序加载和数据库连接管理。开发者只需提供数据库连接信息,然后通过它来获取连接并执行SQL查询,而无需了解驱动程序加载、连接池等底层细节。

    通过这种方式,JDBC使得与各种数据库交互变得更加简单和统一,开发者只需关注业务逻辑和SQL查询,而无需处理复杂的数据库连接管理。这正是外观模式的一个典型应用,简化了复杂系统的接口,提供了一个更高级别、更易用的界面。

  • 相关阅读:
    Leetcode 目标和(递归)
    细说雪花算法
    centOS7| 编译安装 gdal 库
    spring-boot 单元测试 faq2
    大数据——Zookeeper 安装(集群)(二)
    8.2 Windows驱动开发:内核解锁与强删文件
    java代码编写,抓取贝壳网前10条数据
    Nginx配置ssl证书实现https访问
    8月汽车销量出炉:问界破万,智己破千,理想腰斩!埃安近创新高
    Linux命令:stat命令
  • 原文地址:https://blog.csdn.net/qq_73574147/article/details/136362777