🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 外观设计模式 > 原文: [https://howtodoinjava.com/design-patterns/structural/facade-design-pattern/](https://howtodoinjava.com/design-patterns/structural/facade-design-pattern/) **外观设计模式**为子系统中的一组接口提供了统一的接口。 外观定义了**更高级别的接口**,使子系统更易于使用。 ## 1.何时使用外观模式 外观模式是**结构型设计模式**中的一种,另外还有四个[设计模式](https://howtodoinjava.com/gang-of-four-java-design-patterns/)。 当我们有一个复杂的系统要以简化的方式向客户公开时,外观模式是合适的。 其目的是将内部复杂性隐藏在从外部看起来很简单的单个接口后面。 外观还可以将使用系统的代码与子系统的细节分离开来,从而使以后修改系统变得更加容易。 ## 2.现实世界中的外观示例 为了了解外观,让我们举一个非常简单的台式计算机示例。 当我们必须启动计算机时,我们要做的就是按下开始按钮。 我们真的不在乎计算机硬件和软件中包含什么。 这是外观模式的一个示例。 在 Java 编程中,我们必须已连接到数据库以获取一些数据。 我们只是调用方法`dataSource.getConnection()`来获取连接,但是在内部发生了很多事情,例如加载驱动程序,创建连接或从池中获取连接,更新统计信息,然后将连接引用返回给调用者方法。 这是编程世界中外观模式的另一个示例。 同样,我们可以找到更多的示例,这些示例隐藏了许多内部复杂性,并为程序员提供了使用简单的接口来与系统一起工作。 所有这些都是外观示例。 ## 3.外观设计模式示例 让我们为演示目的编写自己的外观实现。 在此示例中,我们将创建一个报告生成器,该报告生成器具有多个步骤来创建任何报告。 例如,它将首先创建报告的页眉,页脚,添加数据行,格式化报告,然后以所需的格式(pdf,html 等)编写报告。 使用`ReportGeneratorFacade`,我们将隐藏所有这些步骤并公开易于使用的方法。 ```java public class Report { private ReportHeader header; private ReportData data; private ReportFooter footer; public ReportHeader getHeader() { return header; } public void setHeader(ReportHeader header) { System.out.println("Setting report header"); this.header = header; } public ReportData getData() { return data; } public void setData(ReportData data) { System.out.println("Setting report data"); this.data = data; } public ReportFooter getFooter() { return footer; } public void setFooter(ReportFooter footer) { System.out.println("Setting report footer"); this.footer = footer; } } ``` ```java public class ReportHeader { } ``` ```java public class ReportFooter { } ``` ```java public class ReportData { } ``` ```java public enum ReportType { PDF, HTML } ``` ```java public class ReportWriter { public void writeHtmlReport(Report report, String location) { System.out.println("HTML Report written"); //implementation } public void writePdfReport(Report report, String location) { System.out.println("Pdf Report written"); //implementation } } ``` ```java import javax.activation.DataSource; public class ReportGeneratorFacade { public static void generateReport(ReportType type, DataSource dataSource, String location) { if(type == null || dataSource == null) { //throw some exception } //Create report Report report = new Report(); report.setHeader(new ReportHeader()); report.setFooter(new ReportFooter()); //Get data from dataSource and set to ReportData object report.setData(new ReportData()); //Write report ReportWriter writer = new ReportWriter(); switch(type) { case HTML: writer.writeHtmlReport(report, location); break; case PDF: writer.writePdfReport(report, location); break; } } } ``` 让我们测试一下外观实现。 ```java import com.howtodoinjava.facade.ReportGeneratorFacade; import com.howtodoinjava.facade.ReportType; public class Main { public static void main(String[] args) throws Exception { ReportGeneratorFacade reportGeneratorFacade = new ReportGeneratorFacade(); reportGeneratorFacade.generateReport(ReportType.HTML, null, null); reportGeneratorFacade.generateReport(ReportType.PDF, null, null); } } ``` 程序输出。 ```java Setting report header Setting report footer Setting report data HTML Report written Setting report header Setting report footer Setting report data Pdf Report written ``` ## 4.常见问题 #### 4.1 外观模式的优点 请记住,外观不会降低复杂性。 它只对外部系统和客户端隐藏它。 因此,外观模式的主要受益者仅是客户端应用和其他系统。 它为客户提供了一个简单的接口,即,我们没有为客户展示一个复杂的子系统,而是为客户提供了一个简化的接口。 它还可以帮助我们减少客户端需要处理的对象数量。 #### 4.2 外观不限制对子系统的访问 外观不封装子系统类或接口。 它只是提供了一个简单的接口(或图层),使我们的生活更轻松。 我们可以自由公开子系统或整个子系统本身的任何功能。 它只会使代码看起来难看,否则它将起作用。 #### 4.3 外观样式与适配器样式 在[适配器模式](https://howtodoinjava.com/design-patterns/structural/adapter-design-pattern-in-java/)中,我们尝试更改接口,以便客户端可以使用系统。 否则,该系统将很难被客户端使用(甚至无法使用)。 外观模式简化了接口。 它为客户端提供了一个与之交互的简单接口(而不是复杂的子系统)。 #### 4.4 外观模式与中介者模式 在中介者模式实现中,子系统知道中介者。 他们互相交谈。 但是在外观中,子系统不了解外观,并且从外观到子系统之间提供了单向通信。 #### 4.5 一个复杂子系统只有一个外观? 一点也不。 我们可以为特定的复杂子系统创建任意数量的外观。 这样做的目的是使系统更易于使用。 它需要创建 N 个外观,然后进行制作。 #### 4.6 外观设计模式的挑战 * 子系统与外观层连接。 因此,您需要注意额外的编码层。 * 当子系统的内部结构发生变化时,您还需要将这些变化合并到外观层中。 学习愉快!