• Java 设计模式——外观模式


    1.概述

    (1)有些人可能炒过股票,但其实大部分人都不太懂,这种没有足够了解证券知识的情况下做股票是很容易亏钱的,刚开始炒股肯定都会想,如果有个懂行的帮帮手就好,其实基金就是个好帮手,支付宝里就有许多的基金,它将投资者分散的资金集中起来,交由专业的经理人进行管理,投资于股票、债券、外汇等领域,而基金投资的收益归持有者所有,管理机构收取一定比例的托管管理费用。

    (2)外观模式 (Facade Pattern) 是一种结构型设计模式,又称为门面模式,它提供了一个统一的接口,用于简化复杂系统或子系统的接口,并将其封装成一个更高级别的接口。外观模式隐藏了系统的复杂性,通过定义一个高层接口,使得客户端与系统的交互更加简单和方便。此外,外观模式是迪米特法则的典型应用。

    在这里插入图片描述

    2.结构

    外观模式包含以下主要角色:

    • 外观 (Facade) 角色:外观对象是客户端与子系统之间的中间层,它封装了一组相关的子系统接口,对客户端提供一个更简单、更高层次的接口。
    • 子系统 (Subsystem) 角色:子系统是完成真正业务逻辑的组件,它包含了一系列相互关联的类和方法。每个子系统都有自己的功能和职责,但客户端可能不需要直接与子系统进行交互。

    3.实现

    【例】智能家电控制:小明的爷爷已经 60 岁了,一个人在家生活:每次都需要打开灯、打开电视、打开空调;睡觉时关闭灯、关闭电视、关闭空调;操作起来都比较麻烦。所以小明给爷爷买了智能音箱,可以通过语音直接控制这些智能家电的开启和关闭。类图如下:
    在这里插入图片描述
    具体实现代码如下:

    3.1.子系统类

    Light.java

    public class Light {
        public void on(){
            System.out.println("打开电灯......");
        }
        
        public void off(){
            System.out.println("关闭电灯......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    TV.java

    public class TV {
        public void on(){
            System.out.println("打开电视机......");
        }
        
        public void off(){
            System.out.println("关闭电视机......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    AirCondition.java

    public class AirCondition {
        public void on(){
            System.out.println("打开空调......");
        }
        
        public void off(){
            System.out.println("关闭空调......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.2.外观类

    SmartAppliancesFacade.java

    //外观类,用户主要和该类对象进行交互
    public class SmartAppliancesFacade {
        //聚合电灯对象、电视机对象、空调对象
        private Light light;
        private TV tv;
        private AirCondition airCondition;
        
        public SmartAppliancesFacade() {
            light = new Light();
            tv = new TV();
            airCondition = new AirCondition();
        }
    
        //通过语言控制
        public void say(String message) {
            if (message.contains("打开")) {
                on();
            } else if (message.contains("关闭")) {
                off();
            } else {
                System.out.println("我还听不懂你说的!!!");
            }
        }
    
        //一件打开功能
        public void on() {
            light.on();
            tv.on();
            airCondition.on();
        }
    
        //一件关闭功能
        public void off() {
            light.off();
            ;
            tv.off();
            airCondition.off();
        }
    }
    
    • 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

    3.3.测试

    Client.java

    public class Client {
        public static void main(String[] args) {
            //创建智能音箱对象
            SmartAppliancesFacade facade = new SmartAppliancesFacade();
            //控制家电
            facade.on();
            System.out.println("==========");
            //关闭家电
            facade.off();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出结果如下:

    打开电灯......
    打开电视机......
    打开空调......
    ==========
    关闭电灯......
    关闭电视机......
    关闭空调......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.优缺点

    (1)外观模式有以下几个优点:

    • 简化客户端的调用:通过外观对象提供的简单接口,客户端可以更方便地与系统进行交互,不需要了解系统的复杂性和内部结构。
    • 将客户端与子系统解耦:外观模式将子系统封装起来,客户端只需要与外观对象进行交互,而不需要与各个子系统直接交互,降低了客户端与子系统之间的耦合度。
    • 提高代码的可维护性:通过将复杂的系统逻辑封装在外观对象中,提升了代码的可读性和可维护性。修改系统时,只需调整外观对象的接口,而不需要修改客户端代码。
    • 提供统一的接口:外观对象为系统的各个子系统定义了一个统一的接口,使得系统更易于理解和使用。

    (2)外观模式也有一些缺点:

    • 过度增加了一个新的抽象层:外观模式引入了一个新的外观对象,可能会导致系统中类的数量增加,从而增加了系统的复杂性。
    • 不符合开闭原则:当系统的功能发生变化时,可能需要修改外观对象的接口,这可能会影响到客户端代码。
    • 不能完全隐藏子系统的复杂性:外观模式可以隐藏一部分子系统的复杂性,但如果客户端需要直接访问子系统的一些细节,就无法避免与子系统发生直接交互。

    5.使用场景

    (1)外观模式适用于以下情况:

    • 当需要简化复杂系统或子系统的接口时,可以使用外观模式。例如,一个系统包含多个子系统,每个子系统有自己的接口,但客户端可能不需要直接调用所有子系统的接口,此时可以使用外观模式将这些子系统接口封装成一个更高层级的接口。
    • 当需要将系统与客户端分离并提高系统可维护性时,可以使用外观模式。通过将系统的复杂性封装到外观对象中,可以减少客户端代码与子系统之间的耦合,并提高代码的可读性和可维护性。
    • 当需要对现有系统进行重构时,可以使用外观模式。通过增加外观对象,可以将系统的接口分层并提高代码的结构性,从而使系统更加易维护。

    (2)总之,外观模式适用于需要简化系统接口、分离客户端与子系统之间的耦合度、提高代码可维护性以及改善系统的可用性和可理解性的情况。它是一个常用的结构型设计模式,在实际开发中有着广泛的应用。

    6.源码解析

    (1)使用 Tomcat 作为 web 容器时,接收浏览器发送过来的请求,Tomcat 会将请求信息封装成 ServletRequest 对象,如下图 ① 处对象。但是仔细想想 ServletRequest 是一个接口,它还有一个子接口 HttpServletRequest,而我们知道该 request 对象肯定是一个 HttpServletRequest 对象的子实现类对象,到底是哪个类的对象呢?可以通过输出 request 对象,我们就会发现是一个名为 RequestFacade 的类的对象。

    在这里插入图片描述
    (2)RequestFacade 类就使用了外观模式。其结构图如下所示:
    在这里插入图片描述

    (3)为什么在此处使用外观模式呢?
    定义 RequestFacade 类,分别实现 ServletRequest ,同时定义私有成员变量 Request ,并且方法的实现调用 Request 的实现。然后,将 RequestFacade上转为 ServletRequest 传给 servlet 的 service 方法,这样即使在 servlet 中被下转为 RequestFacade ,也不能访问私有成员变量对象中的方法。既用了 Request ,又能防止其中方法被不合理的访问。

  • 相关阅读:
    解决风控模型的过拟合与算法高效求解,来试试这种经典解决方法
    在项目中使用flex布局的justify-content:space-around;遇到的问题,(数量为单数)
    【if 的高阶用法练习题】if only / I wish
    CH559L单片机ADC多通道采样数据串口打印案例
    【ESP32--FreeRTOS 任务间的同步与通信】
    新学期,不再迷茫畏惧,我想这样度过大四
    【概率论基础进阶】随机事件和概率-古典概型与伯努利概型
    Mysql笔记2
    Linux之文件/目录搜索
    提高matlab运算效率——预分配内存
  • 原文地址:https://blog.csdn.net/weixin_43004044/article/details/134247157