• 外观模式简介


    概念

    外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式隐藏了子系统的复杂性,并将其封装在一个简单易用的接口中,使得客户端可以更方便地使用子系统。

    特点

    1. 提供了一个简化和统一的接口,隐藏了底层子系统的复杂性。
    2. 将客户端与子系统之间解耦,降低了客户端代码与子系统之间的直接依赖关系。
    3. 通过外观类来集中管理和协调多个相关对象,提高了代码可维护性和灵活性。

    优点

    1. 简化客户端与复杂子系统之间的交互过程。
    2. 隐藏底层实现细节,提高代码可读性和可维护性。
    3. 降低耦合度,减少对其他代码影响。

    缺点

    1. 如果需要修改或扩展功能,则可能需要修改外观类本身。
    2. 外观类承担较多职责时会变得臃肿。

    适用场景

    1. 当存在一个复杂数量较大且关联紧密的类库时,可以使用外观模式将其封装成一个简单易用、统一的接口。
    2. 当需要简化一个复杂子系统的接口,并提供一个更高层次的接口供客户端使用时,可以使用外观模式。

    实现方式

    单一外观类

    实现原理

    1. 定义一个外观类,该类包含对子系统的引用。
    2. 在外观类中定义方法,每个方法代表一个功能或操作。在方法内部调用相应子系统的方法来完成具体逻辑。
    3. 客户端通过直接调用外观类的方法来使用子系统。

    实现代码

    1. // 子系统A
    2. class SubSystemA {
    3. public void operationA() {
    4. System.out.println("SubSystemA operation");
    5. }
    6. }
    7. // 子系统B
    8. class SubSystemB {
    9. public void operationB() {
    10. System.out.println("SubSystemB operation");
    11. }
    12. }
    13. // 外观类
    14. class Facade {
    15. private SubSystemA subSystemA;
    16. private SubSystemB subSystemB;
    17. public Facade() {
    18. this.subSystemA = new SubSystemA();
    19. this.subSystemB = new SubSystemB();
    20. }
    21. public void operation() {
    22. subSystemA.operationA();
    23. subSystemB.operationB();
    24. }
    25. }
    26. public class Main {
    27. public static void main(String[] args) {
    28. Facade facade = new Facade(); // 创建外观类对象
    29. facade.operation(); // 调用外观类的方法,实现对子系统的操作
    30. }
    31. }

    在上述示例中,SubSystemASubSystemB分别代表两个子系统。Facade是单一外观类,封装了对这两个子系统的引用,并提供了一个名为operation()的方法来调用这两个子系统的具体操作。客户端通过创建一个外观数对象,并调用其方法来使用子系统。在此示例中,客户端只需要与外观类进行交互,而无需直接与子系统进行交互。

    存在问题:
     

    1. 如果有多个不同类型的客户端需要访问不同功能集合,则可能需要修改和扩展单一外观类。
    2. 单一外观类承担了较多职责,导致代码变得庞大而复杂。

    多个外观类

    实现原理

    1. 定义多个外观类,每个外观类分别与一个或多个子系统相关联。
    2. 在每个外观类中定义方法,每个方法代表一个功能或操作。在方法内部调用相应子系统的方法来完成具体逻辑。
    3. 客户端根据需要选择合适的外观数进行调用。

    实现代码

    1. // 子系统A
    2. class SubSystemA {
    3. public void operationA() {
    4. System.out.println("SubSystemA operation");
    5. }
    6. }
    7. // 子系统B
    8. class SubSystemB {
    9. public void operationB() {
    10. System.out.println("SubSystemB operation");
    11. }
    12. }
    13. // 外观类
    14. class Facade1 {
    15. private SubSystemA subSystemA;
    16. public Facade1() {
    17. this.subSystemA = new SubSystemA();
    18. }
    19. public void operation() {
    20. subSystemA.operationA();
    21. }
    22. }
    23. // 另一个外观类
    24. class Facade2 {
    25. private SubSystemB subSystemB;
    26. public Facade2() {
    27. this.subSystemB = new SubSystemB();
    28. }
    29. public void operation() {
    30. subSystemB.operationB();
    31. }
    32. }
    33. public class Main {
    34. public static void main(String[] args) {
    35. Facade1 facade1 = new Facade1(); // 创建外观数对象1
    36. Facade2 facade2 = new Facade2(); // 创建外观数对象2
    37. facade1.operation(); // 调用外观数对象1的方法,实现对子系统A的操作
    38. facade2.operation(); // 调用外观数对象2的方法,实现对子系统B的操作
    39. }
    40. }

    在上述示例中,SubSystemASubSystemB分别代表两个不同的子系统。Facade1Facade2是两个独立的外观类,分别封装了对这两个子系统的引用,并提供了一个名为 operation() 的方法来调用相应子系统的具体操作。客户端根据需要选择合适的外观类进行调用。在此示例中,客户端可以选择使用 Facade1  Facade2 来访问特定子系统。这样客户端只需要与所选外观类进行交互,而无需直接与各个子系统进行交互。

    嵌套调用

    实现原理

    1. 定义多个外观类,每个外观类负责封装和管理特定子系统的操作。
    2. 在一个外观类的操作方法内部,通过创建其他外观类对象并调用其相应的方法来实现嵌套调用。
    3. 客户端只需要与最上层的外观数进行交互,无需关心底层具体子系统。

    实现代码

            

    1. // 子系统A
    2. class SubSystemA {
    3. public void operationA() {
    4. System.out.println("SubSystemA operation");
    5. }
    6. }
    7. // 子系统B
    8. class SubSystemB {
    9. public void operationB() {
    10. System.out.println("SubSystemB operation");
    11. }
    12. }
    13. // 外观类
    14. class Facade1 {
    15. private SubSystemA subSystemA;
    16. private Facade2 facade2;
    17. public Facade1() {
    18. this.subSystemA = new SubSystemA();
    19. this.facade2 = new Facade2();
    20. }
    21. public void operation() {
    22. subSystemA.operationA();
    23. facade2.operation(); // 嵌套调用Facade2的操作方法
    24. }
    25. }
    26. // 另一个外观类
    27. class Facade2 {
    28. private SubSystemB subSystemB;
    29. public Facade2() {
    30. this.subSystemB = new SubSystemB();
    31. }
    32. public void operation() {
    33. subSystemB.operationB();
    34. }
    35. }
    36. public class Main {
    37. public static void main(String[] args) {
    38. Facade1 facade1 = new Facade1(); // 创建外观类对象
    39. facade1.operation(); // 调用外观类对象的方法,实现对子系统A和子系统B的嵌套调用
    40. }
    41. }

    在上述示例中,SubSystemASubSystemB分别代表两个不同的子系统。Facade1是一个外观类,封装了对这两个子系统的引用,并提供了一个名为 operation() 的方法来调用相应子系统的具体操作。在 operation() 方法内部,除了调用 subsystemA.operationA() 外,还创建并使用了 Facade2 对象,并通过其 operation() 方法实现对另一个子系统 B 的操作。

    客户端只需要与最上层的外观数进行交互,即调用 facade1.operation() 方法。这样客户端无需关心底层具体子系统及其嵌套调用逻辑,通过外观类的嵌套调用,实现了对多个子系统的操作。

    存在问题:

    1. 嵌套过深可能导致代码可读性降低和维护困难。
    2. 如果有新的子系统加入或旧的子系统变更,需要修改和扩展相应的嵌套逻辑。
  • 相关阅读:
    重入锁ReentrantLock详解
    【问题排查篇】一次业务问题对 ES 的 cardinality 原理探究
    【Java第33期】:在普通的Maven项目中存储Bean对象并获取和使用
    Java Servlet关键点详解
    Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog
    安卓‘进度条ProgressBar’中‘setIndeterminate()’方法
    常用日期类
    mysql-mysql的安装和一些基本设置
    openvino多输入多输出动态尺寸样例记录
    跟李沐学AI-动手学深度学习1
  • 原文地址:https://blog.csdn.net/aidscooler/article/details/132671951