设计模式之外观模式

1、详细介绍

        外观模式(Facade Pattern)是一种结构型设计模式,它为子系统的一组接口提供了一个统一的入口点(外观类)。外观模式简化了客户端与子系统之间的交互,屏蔽了子系统内部的复杂性,使客户端能够以更简单的方式使用子系统。

2、主要角色

  • Facade(外观):为子系统提供一个统一的接口,定义一组高层接口供客户端使用。外观类负责将客户端请求转发到适当的子系统对象。
  • Subsystems(子系统):包含一系列相关的类(接口和实现类),共同完成一个特定的业务功能。子系统并不知道外观的存在,它们通常会提供更底层、更具体的接口。

3、使用场景

  1. 简化复杂接口:当子系统的接口过于复杂,或者客户端与子系统之间存在过多的依赖关系时,可以使用外观模式简化接口,降低客户端的使用难度。
  2. 子系统聚合:当需要将多个子系统整合为一个整体,提供统一的访问接口时,外观模式可以将子系统之间的交互封装在外观类中,对外部隐藏子系统的内部细节。
  3. 分阶段开发:在系统开发初期,可以先提供一个简单的外观类,随着系统逐渐完善,再逐步添加更复杂的子系统功能。

4、Java代码示例

        假设我们正在开发一个智能家居系统,包含灯光、空调、电视等多个子系统。我们可以使用外观模式为这些子系统提供一个统一的接口:

// Subsystems(子系统)
interface Light {
    void turnOn();
    void turnOff();
}

class SmartLight implements Light {
    @Override
    public void turnOn() {
        System.out.println("Turning on smart light.");
    }

    @Override
    public void turnOff() {
        System.out.println("Turning off smart light.");
    }
}

interface AirConditioner {
    void coolDown();
    void warmUp();
}

class SmartAirConditioner implements AirConditioner {
    @Override
    public void coolDown() {
        System.out.println("Cooling down the room.");
    }

    @Override
    public void warmUp() {
        System.out.println("Warming up the room.");
    }
}

interface Television {
    void turnOn();
    void turnOff();
    void changeChannel(int channel);
}

class SmartTelevision implements Television {
    @Override
    public void turnOn() {
        System.out.println("Turning on smart TV.");
    }

    @Override
    public void turnOff() {
        System.out.println("Turning off smart TV.");
    }

    @Override
    public void changeChannel(int channel) {
        System.out.println("Changing to channel " + channel + ".");
    }
}

// Facade(外观)
class HomeTheaterFacade {
    private Light light;
    private AirConditioner airConditioner;
    private Television television;

    public HomeTheaterFacade(Light light, AirConditioner airConditioner, Television television) {
        this.light = light;
        this.airConditioner = airConditioner;
        this.television = television;
    }

    public void startWatchingMovie() {
        light.turnOn();
        airConditioner.coolDown();
        television.turnOn();
        television.changeChannel(1);
    }

    public void endWatchingMovie() {
        light.turnOff();
        airConditioner.warmUp();
        television.turnOff();
    }
}

// Client(客户端)
public class Client {
    public static void main(String[] args) {
        Light light = new SmartLight();
        AirConditioner airConditioner = new SmartAirConditioner();
        Television television = new SmartTelevision();

        HomeTheaterFacade homeTheater = new HomeTheaterFacade(light, airConditioner, television);
        homeTheater.startWatchingMovie();
        System.out.println("Watching movie...");
        homeTheater.endWatchingMovie();
    }
}

5、注意事项

  1. 外观类的职责:外观类应该仅负责协调子系统的交互,而不应包含任何业务逻辑。如果外观类过于庞大,可能意味着它承担了过多职责,需要进行拆分。
  2. 避免过度封装:虽然外观模式旨在简化接口,但如果过度封装,可能会隐藏过多子系统的功能,限制系统的灵活性。应根据实际需求,平衡接口的简化和功能的暴露。

6、优缺点

优点

  • 简化接口:外观模式为子系统提供了一个简化的、易于使用的接口,降低了客户端的使用难度。
  • 减少系统间的耦合:通过外观类,客户端无需直接与子系统交互,减少了客户端与子系统之间的耦合。
  • 易于扩展:新增子系统或修改子系统功能时,只需修改外观类即可,不影响客户端代码。

缺点

  • 可能隐藏子系统功能:如果外观类过度封装,可能会隐藏子系统的某些功能,限制系统的灵活性。
  • 增加额外的类:使用外观模式需要额外创建外观类,增加了系统的复杂性。

7、使用过程中可能遇到的问题及解决方案

  1. 外观类过于庞大:如果外观类包含了过多的协调逻辑,可能会变得庞大且难以维护。

    解决方案:遵循单一职责原则,将外观类拆分为多个小的外观类,每个外观类负责协调一部分子系统的交互。或者,对于复杂的协调逻辑,可以考虑使用命令模式或中介者模式。

  2. 子系统间的依赖关系复杂:如果子系统间的依赖关系复杂,可能会导致外观类的实现困难。

    解决方案:梳理和简化子系统间的依赖关系,或者使用依赖注入框架(如Spring)来管理依赖关系。对于复杂的依赖关系,可以考虑使用享元模式、策略模式等进行优化。

8、与其他模式的对比

  • 与适配器模式相比:外观模式和适配器模式都涉及接口的转换,但外观模式的目标是简化接口,而适配器模式的目标是解决接口不兼容问题。
  • 与代理模式相比:外观模式和代理模式都涉及对象的封装,但外观模式侧重于简化子系统的使用,而代理模式侧重于控制对象的访问,如添加额外的逻辑(如权限控制、日志记录等)或实现远程访问。

注意:

        外观模式通过提供一个统一的接口,简化了客户端与子系统之间的交互,适用于简化复杂接口、子系统聚合以及分阶段开发等场景。在使用过程中,应注意外观类的职责、避免过度封装,并了解其优缺点。针对外观类过于庞大、子系统间的依赖关系复杂等问题,应采取相应解决方案。同时,应理解外观模式与其他模式(如适配器模式、代理模式)的区别。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/571494.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity】UnityEvent(一)

​UnityEvent----高效管理游戏事件的利器 在游戏开发中,事件系统是实现各种功能的关键组成部分。它允许我们将不同对象之间的交互解耦,使得代码更加模块化和易于维护。而UnityEvent作为Unity引擎提供的一种强大的事件系统工具,为开发者提供了…

c++ - 模板(一)

文章目录 一、函数模板 一、函数模板 1、概念 函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定 类型版本。 2、原理 函数模板是一个蓝图,它本身并不是函数,是编译器用…

宜搜科技死磕港交所上市:从搜索引擎到广告投放,业绩疲态凸显

近日,宜搜科技控股有限公司(下称“宜搜科技”)向港交所递交招股书,计划在香港主板上市,中银国际为其独家保荐人。 值得注意的是,宜搜科技已在资本市场辗转多年。该公司曾于2014年向纽交所递交上市申请&…

Web3与传统互联网:挑战、融合与共生

引言 Web3技术正以惊人的速度改变着我们的互联网体验。作为一个基于区块链的去中心化互联网模型,Web3不仅带来了创新和变革,还引发了与传统互联网之间的对比和讨论。本文将深入探讨Web3与传统互联网之间的关系,挑战,以及可能的融…

智慧火电厂合集 | 数字孪生助推能源革命

火电厂在发电领域中扮演着举足轻重的角色。主要通过燃烧如煤、石油或天然气等化石燃料来产生电力。尽管随着可再生能源技术的进步导致其比重有所减少,但直至 2023 年,火电依然是全球主要的电力来源之一。 通过图扑软件自主研发 HT for Web 产品&#xf…

模块三:二分——162.寻找峰值

文章目录 题目描述算法原理解法一:暴力查找解法二:二分查找 代码实现解法一:暴力查找解法二:CJava 题目描述 题目链接:162.寻找峰值 根据题意,需要使用O(log N)的时间复杂度来解决,得出本道题…

对浅拷贝的理解

问题背景 我之前一直以为浅拷贝出来的新对象和旧对象的引用地址是相同的,但是通过Object和发现浅拷贝的新对象和旧对象的引用地址不同!! const obj1 { name: "Alice", test: { age: 12 } };const obj4 Object.assign({}, obj1);…

linux中 虚拟机 修改时间 centos7

方法1 :虚拟机内 设置 方法2 代码实现 timedatectl set-timezone "Asia/Shanghai"

iOS 17上如何恢复数据?iOS 17 数据恢复软件

“您好,我正在为我的 iPhone 寻找一款iOS 17 数据恢复软件。升级到 iOS 17 后,我丢失了 iPhone 上的所有照片、联系人和消息。有什么建议吗?” ——丹尼 iOS 17数据恢复软件下载 升级到iOS 17后如何恢复丢失的数据?由于在 iPhone…

Django中的事务

1 开启全局的事务 DATABASES {default: {ENGINE: django.db.backends.mysql, # 使用mysql数据库NAME: tracerbackend, # 要连接的数据库USER: root, # 链接数据库的用于名PASSWORD: 123456, # 链接数据库的用于名HOST: 192.168.1.200, # mysql服务监听的ipPORT: 3306, …

目标检测——小麦穗头数据集

一、重要性及意义 小麦穗头检测在农业领域具有重要意义,主要体现在以下几个方面: 首先,小麦穗头检测可以帮助农民和植物科学家准确评估作物的健康状况和成熟度。通过对小麦穗部的形态特征进行测量和分析,可以及时发现作物生长过…

应用在防蓝光显示器中的LED防蓝光灯珠

相比抗蓝光眼镜、防蓝光覆膜、软体降低蓝光强度这些“软”净蓝手段,通过对LED的发光磷粉进行LED背光进行技术革新,可实现硬件“净蓝”。其能够将90%以上的有害蓝光转换为450nm以上的长波低能光线,从硬件的角度解决了蓝光危害眼睛的问题&#…

python+django校园社交高校交友网站2x7r5.

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行,将系统所使用到的表以及数据存储到MySQL数据库中,方便对数据进行操作本课题基于WEB的开发平台,设计的基本思路是: 前端:vue.jselementui 框架&#…

【机器学习】深度神经网络(DNN):原理、应用与代码实践

深度神经网络(DNN):原理、应用与代码实践 一、深度神经网络(DNN)的基本原理二、DNN的优缺点分析三、DNN的代码实践四、总结与展望 在人工智能与机器学习的浪潮中,深度神经网络(Deep Neural Netw…

Spring Boot 集成 EasyExcel 3.x

Spring Boot 集成 EasyExcel 3.x Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel(优雅实现Excel导入导出)。 🤖 Spring Boot 2.x 实践案例(代码仓库) 介绍 EasyExcel 是一个基于 Java 的、…

【注解和反射】什么时候类会和不会被初始化?

继上一篇博客【注释和反射】类加载的过程-CSDN博客 目录 四、什么时候类会被初始化(主动引用)? 测试 五、什么情况下不会发生类的初始化(被动引用)? 测试 四、什么时候类会被初始化(主动引用…

<网络> HTTP

目录 前言: 一、再谈协议 (一)认识URL (二)Encode 和 Decode 二、HTTP 协议 (一)协议格式 (二)见一见请求 (三)见一见响应 三、模拟实现响…

模块化 DeFi L2 “Mode” 整合 Covalent Network(CQT),以获 Web3 最大数据集的支持

Covalent Network(CQT),作为 Web3 领先的数据层,宣布其统一 API 将与 Mode 集成,以加快其基于以太坊构建的专注于 DeFi 的模块化 Layer2 方案的数据访问速度。这一战略合作将通过为开发者提供更强大的工具和能力&#…

论文浅尝 | LoRA: 大模型的低秩适配

笔记整理:陈一林,东南大学硕士,研究方向为不确定知识图谱规则学习 链接:https://arxiv.org/abs/2106.09685 1、动机 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练,然后对特定任务或领域进行适应性…

`THREE.AudioAnalyser` 音频分析

demo案例 THREE.AudioAnalyser 音频分析 入参 (Input Parameters): audio: 一个 THREE.Audio 实例,代表要分析的音频。fftSize: 快速傅里叶变换(FFT)的大小,用于确定分析的精度和频率分辨率。smoothingTimeConstant: 平滑时间…