Java设计模式:外观模式之优雅门面(九)

news2024/11/28 14:42:19

在这里插入图片描述

码到三十五 : 个人主页

心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 !


在软件工程中,设计模式是解决常见设计问题的经验总结,它为开发者提供了一种通用的、可复用的解决方案。外观模式(Facade
Pattern)作为结构型设计模式的一种,通过为子系统中的一组接口提供一个统一的高层接口,使得子系统更加容易使用。

目录

    • 一、外观模式的起源与背景
    • 二、外观模式的组件
      • 2.1. Facade(外观类)
      • 2.2. Subsystem Classes(子系统类)
      • 2.3. Client(客户端)
    • 三、外观模式的优势分析
    • 四、外观模式实现方式
    • 五、外观模式的应用场景举例
    • 总结

[参见]:

Java设计模式:核心概述(一)

Java设计模式:单例模式之六种实现方式详解(二)

Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)

Java设计模式:建造者模式之经典与流式的三种实现(四)

Java设计模式:适配器模式的三种形式(五)

Java设计模式:深入装饰器模式的三种写法(六)

Java设计模式:组合模式之透明与安全的两种实现(七)

Java设计模式:代理模式的静态和动态之分(八)

一、外观模式的起源与背景

在复杂的软件系统中,往往存在多个子系统或组件协同工作的情况。这些子系统可能由不同的团队开发,使用不同的技术栈,具有各自独特的接口和依赖关系。当客户端需要使用这些子系统时,可能需要了解并调用多个接口,处理复杂的依赖关系,这无疑增加了客户端的使用难度。

为了解决这个问题,外观模式应运而生。它通过一个外观类(Facade)来整合子系统中的接口,为客户端提供一个统一的、更简单的接口。客户端只需与外观类交互,而无需了解子系统的具体实现细节和复杂性。

二、外观模式的组件

在这里插入图片描述

2.1. Facade(外观类)

  • 外观类是外观模式的核心组件,它提供了客户端所需的统一接口。
  • 外观类内部持有对子系统对象的引用,负责将客户端的请求转发给相应的子系统对象处理。
  • 外观类可以对子系统的接口进行封装和抽象,使得客户端无需了解子系统的具体实现细节。
  • 外观类还可以对子系统的返回结果进行整合和处理,以更友好的方式呈现给客户端。

2.2. Subsystem Classes(子系统类)

  • 子系统类是实现具体功能的类,它们可能具有复杂的接口和相互依赖关系。
  • 在外观模式中,子系统类被隐藏起来,客户端不直接访问它们。而是通过外观类来间接访问子系统。
  • 子系统类之间可能存在复杂的交互和协作关系,但这些细节对客户端来说是透明的。

2.3. Client(客户端)

  • 客户端是使用外观类来访问子系统的类。
  • 客户端只需了解外观类提供的接口,而无需了解子系统的具体实现细节和复杂性。
  • 通过使用外观类,客户端可以更加简洁、方便地访问子系统,降低了客户端的使用难度和耦合度。

三、外观模式的优势分析

  1. 简化客户端使用:通过提供一个统一的接口,外观模式使得客户端可以更加简洁、方便地访问子系统。客户端无需了解子系统的复杂性和实现细节,只需调用外观类提供的方法即可完成操作。这降低了客户端的使用难度和学习成本。
  2. 降低耦合度:外观模式将客户端与子系统解耦,客户端只需与外观类交互,而无需直接依赖子系统。当子系统发生变化时,只需要修改外观类而无需修改客户端代码。这提高了系统的可维护性和可扩展性。
  3. 隐藏系统复杂性:外观类封装了子系统的实现细节和复杂性,为客户端提供了一个清晰的、一致的视图。这使得客户端可以专注于自己的业务逻辑,而无需关心子系统的具体实现和交互细节。这有助于保护子系统的内部结构和实现细节不被外部直接访问和修改。
  4. 提高系统灵活性:通过引入外观类作为中介层,我们可以更加灵活地组织和管理子系统。我们可以根据需要添加、删除或修改子系统的组件,而无需修改客户端代码。这提高了系统的灵活性和可配置性。

四、外观模式实现方式

我们模拟一个银行系统,其中包括账户管理、贷款服务和存款服务等多个子系统。然后使用外观模式来提供一个统一的接口给客户端使用。

首先,我们定义几个子系统类(Subsystem Classes),这些类模拟了银行系统中的不同组件。

// 账户管理子系统
class AccountManagement {
    public void createAccount(String accountName) {
        System.out.println("为 " + accountName + " 创建账户。");
    }

    public void closeAccount(String accountName) {
        System.out.println("关闭 " + accountName + " 的账户。");
    }
}

// 贷款服务子系统
class LoanService {
    public void applyForLoan(String accountName, double amount) {
        System.out.println(accountName + " 申请了 " + amount + " 的贷款。");
    }

    public void approveLoan(String accountName) {
        System.out.println(accountName + " 的贷款已被批准。");
    }
}

// 存款服务子系统
class DepositService {
    public void deposit(String accountName, double amount) {
        System.out.println(accountName + " 存款 " + amount + "。");
    }

    public void withdraw(String accountName, double amount) {
        System.out.println(accountName + " 取款 " + amount + "。");
    }
}

接下来,我们创建外观类(Facade),该类将封装这些子系统类,并为客户端提供一个统一的接口。

// 银行外观类
class BankFacade {
    private AccountManagement accountManagement;
    private LoanService loanService;
    private DepositService depositService;

    // 构造函数,初始化子系统对象
    public BankFacade() {
        accountManagement = new AccountManagement();
        loanService = new LoanService();
        depositService = new DepositService();
    }

    // 提供给客户端的简化方法 - 开户并存款
    public void openAccountAndDeposit(String accountName, double amount) {
        accountManagement.createAccount(accountName);
        depositService.deposit(accountName, amount);
        System.out.println("开户并存款操作完成。");
    }

    // 提供给客户端的简化方法 - 申请贷款并批准
    public void applyAndApproveLoan(String accountName, double amount) {
        loanService.applyForLoan(accountName, amount);
        loanService.approveLoan(accountName);
        System.out.println("申请并批准贷款操作完成。");
    }

    // 提供给客户端的简化方法 - 取款并关闭账户
    public void withdrawAndCloseAccount(String accountName, double amount) {
        depositService.withdraw(accountName, amount);
        accountManagement.closeAccount(accountName);
        System.out.println("取款并关闭账户操作完成。");
    }
}

最后,我们创建客户端(Client)来使用外观类。

// 客户端
public class BankClient {
    public static void main(String[] args) {
        // 创建银行外观对象
        BankFacade bankFacade = new BankFacade();

        // 客户端通过银行外观对象调用操作
        bankFacade.openAccountAndDeposit("张三", 10000);
        bankFacade.applyAndApproveLoan("张三", 5000);
        bankFacade.withdrawAndCloseAccount("张三", 2000);
    }
}

客户端通过BankFacade类的简化方法来完成一系列复杂的操作,如开户并存款、申请贷款并批准、取款并关闭账户等。客户端无需了解子系统的具体实现细节和它们之间的交互方式。

运行BankClient类的main方法,看到以下输出:

为 张三 创建账户。
张三 存款 10000.0。
开户并存款操作完成。
张三 申请了 5000.0 的贷款。
张三 的贷款已被批准。
申请并批准贷款操作完成。
张三 取款 2000.0。
关闭 张三 的账户。
取款并关闭账户操作完成。

通过银行外观类,客户端成功地完成了一系列复杂的银行业务操作,而无需直接与各个子系统打交道。这样的设计降低了客户端与子系统之间的耦合度,提高了系统的可维护性和可扩展性。

五、外观模式的应用场景举例

  1. 在大型软件系统中整合不同模块:在大型软件系统中,往往存在多个模块或组件协同工作的情况。这些模块可能由不同的团队开发,具有各自独特的接口和依赖关系。通过使用外观模式,我们可以将这些模块的接口整合成一个统一的接口,使得其他模块可以更加简洁、方便地访问它们。
  2. 隐藏复杂系统的实现细节:当一个系统的实现细节非常复杂时,我们可以使用外观模式来隐藏这些细节。通过提供一个简化的接口给客户端使用,我们可以保护系统的内部结构和实现细节不被外部直接访问和修改。这有助于确保系统的稳定性和安全性。
  3. 在分布式系统中整合服务:在分布式系统中,往往存在多个服务协同工作的情况。这些服务可能部署在不同的服务器上,具有各自独特的接口和通信协议。通过使用外观模式,我们可以将这些服务的接口整合成一个统一的接口,使得客户端可以更加简洁、方便地访问它们。这降低了客户端与分布式系统之间的通信复杂性和耦合度。

总结

外观模式是一种非常实用的设计模式,它通过引入一个统一的接口来隐藏系统的复杂性,使得客户端可以更方便地使用子系统。在实际应用中,我们应该根据具体的需求和场景来选择合适的设计模式,以提高软件系统的可维护性、可扩展性和可重用性。外观模式为我们提供了一个有效的手段来简化客户端的使用和降低系统的复杂性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

同样是测痛仪有什么不一样?大小鼠足底光热刺痛仪VS大小鼠鼠尾测痛仪

简单介绍: ZL-024E大小鼠足底光热刺痛仪是应用在痛觉生理学、药理学等痛觉研究的仪器。可自动测定大/小鼠在自由状态下足底光热刺激痛阈时间,操作简便,并且可自动得出测定结果,是用于药理实验中研究镇痛**的理想实验仪器。 详情…

编程网站推荐

这里是我的一些喜欢用的编程可以用到的网站 json在线格式化校验工具 随机密码生成

关于近期上架过包的一些总结分享

近期过包包体很多,所以遇到的一些问题也是很多很杂,但是基本上都解决了。少部分因为政策原因导致的包体问题封号,这类就只能先排查问题,再重新制作了。对于拒审问题的解决,希望各位开发者能留下相关流程截图&#xff0…

使用nodejs搭建脚手架工具并发布到npm中

使用nodejs搭建脚手架工具并发布到npm中 一、安装环境依赖及脚手架搭建过程二、搭建Monorepo 风格的脚手架工程三、脚手架的必备模块命令参数模块获取命令参数设置子命令用户交互模块文件拷贝模块脚手架中的路径处理目录守卫文件拷贝模块动态文件生成模块mustache简介自动安装依…

Java 开发篇+一个简单的数据库管理系统ZDB

说明:本文供数据库爱好者和初级开发人员学习使用 标签:数据库管理系统、RDBMS、Java小程序、Java、Java程序 系统:Windows 11 x86 CPU :Intel IDE :IntelliJ IDEA Community Edition 2024 语言:Java语言 标…

在线JSON工具

功能支持 ctrls json格式化游览器本地保存ctrla ctrlc 自动检测选中范围是否是全选,然后按照格式化方式添加到粘贴板中json 粘贴JSON自动格式化json可视化修改json压缩复制json层级折叠json关键key 搜索(自动提示高亮)满足某些近视的可以自行调整字体大小, 并且会游…

React复习全攻略:重温旧知,收获新知

简介 大背景: 起源于 Facebook 的内部项目,因为对市面上所有JS MVC框架不满意,就自己开发了一套,用来开发Instagram项目。(开源时间:2013年5月) 三句话解释: 是用于构建 Web 和原…

MWeb Pro For Mac v4.5.9 强大的 Markdown 软件中文版

MWeb 是专业的 Markdown 写作、记笔记、静态博客生成软件,目前已支持 Mac,iPad 和 iPhone。MWeb 有以下特色: 软件下载:MWeb Pro For Mac v4.5.9 软件本身: 使用原生的 macOS 技术打造,追求与系统的完美结合…

OpenImageDebugger - CLion研究

在windows下有vistual studio,针对opencv有image watch,在ubuntu下用Clion插件Image Watch要收费,遂研究OpenImageDebugger与CLion问题,还有些未研究透彻,先记录当前部分。 Open Image Debugger Open Image Debugger …

Linux文件IO(4):目录操作和文件属性获取

目录 1. 前言 2. 函数介绍 2.1 访问目录 – opendir 2.2 访问目录 – readdir 2.3 访问目录 – closedir 2.4 修改文件访问权限 – chmod/fchmod 2.5 获取文件属性 – stat/lstat/fstat 2.5.1 文件属性 – struct stat 2.6 文件类型 – st_mode 3. 代码练习 3.1 要求 3.2 代…

深度挖掘商品信息,jd.item_get API助您呈现商品全面规格参数

深度挖掘商品信息,特别是在电商平台上,对于商家、开发者和用户来说都至关重要。jd.item_get API作为京东开放平台提供的一个强大工具,能够帮助用户轻松获取商品的全面规格参数,进而为商品分析、推荐、比较等提供有力的数据支撑。 …

灵猫论文靠谱不 #职场发展#职场发展

对于许多学生和研究人员来说,写论文是一个耗时且具有挑战性的任务。在撰写论文的过程中,除了要进行繁琐的写作工作外,还需要花费大量时间来查找资料、整理文献、检查语法和格式等。为了帮助大家轻松完成论文写作,现在有了许多写作…

【QT入门】Qt自定义控件与样式设计之QPushButton常用qss

往期回顾 【QT入门】Qt自定义控件与样式设计之qss介绍(Qt style sheet)-CSDN博客 【QT入门】 Qt自定义控件与样式设计之qss选择器-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QLineEdit的qss使用-CSDN博客 【QT入门】Qt自定义控件与样式设计之QPushButton常用qss 这里我们主…

本地电脑渲染不行怎么解决?自助式渲染助你渲染无忧

有时候,即使购买了昂贵的新电脑,我们也可能会遇到渲染速度缓慢、画质不佳或渲染失败等问题。这些问题可能由多种因素引起。针对该问题,为大家推荐了自助式的渲染,解决你本地电脑渲染不佳问题。 电脑渲染不行原因 新电脑渲染效果不…

亚马逊AWS上怎么创建Linux 服务器?操作难不难?

AWS(Amazon Web Services)是全球领先的云服务器提供商之一。你可以使用 AWS 平台在一分钟内设置完服务器。在 AWS 上,你可以微调服务器的许多技术细节,如 CPU 数量,内存和磁盘空间,磁盘类型(更快的 SSD 或者经典的 IDE)等。关于 A…

【linux】set ff=unix、linux设置文件格式

文章目录 一、文件格式二、如何查看文件格式三、设置文件格式、set ffunix四、查看unix与dos的区别 一、文件格式 当我们打开sh脚本时发现有时候格式是unix(LF) ,有时候是windows(CR LF) 。如下图: 文件格式影响了文件中的换行符 linux中sh类型的文件一般要设置为…

测试必备:网站崩溃原因大揭秘!12种常见问题一网打尽

网站崩溃是研发团队最怕看到的情况,但是由于种种原因却时常出现,作为测试人员,我们更应该比一般人了解网站崩溃的原因及排查方法,这是我们测试工作的重要一环。接下来我就谈谈12种常见的网站崩溃原因以及如何跟踪和解决它们。 你的…

纯小白蓝桥杯备赛笔记--DAY10(字符串)

文章目录 KMP字符串哈希算法简介:斤斤计较的小z--2047字符串hash Manacher回文串的性质算法简介最长回文子串 字典树基础朴素字符串查找步骤前缀判定--1204 01tire算法简介:例题1:例题2: KMP字符串哈希 算法简介: 真前…

js将对象数组中的某个属性值,批量替换成另一个数值

前提:对接口数据进行替换。把对应的数值或者字符串替换成中文。。。 核心代码: const toStr {sh: "沪",sz: "深", };myArr.map((item) > {const placeCode item.placeCode;item.placeCode toStr[placeCode] ? toStr[placeC…

Xshell连接不上Ubuntu

1 ubuntu安装ssh服务器 sudo apt install openssh-server修改配置文件vi /etc/ssh/sshd_config 修改如下两个配置 修改完运行下面代码。再用 xhell连接试试。 /etc/init.d/ssh restart