Java设计模式之结构型-外观模式(UML类图+案例分析)

news2024/12/25 12:33:11

目录

一、基础概念

二、UML类图

三、角色设计

四、案例分析

五、总结


一、基础概念

外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

二、UML类图

三、角色设计

角色描述
外观角色为多个子系统对外提供一个统一的接口,外观模式的核心,客户端可以调用这个接口实现对各个子系统的访问
子系统角色实现系统的部分功能,客户可以通过外观角色访问它们,子系统对外界隐藏了内部的复杂性
客户端角色通过一个外观角色访问各个子系统的功能,客户可以根据需要直接访问子系统类

四、案例分析

外观模式就像一个遥控器,它把许多电器的开关集中到了一个遥控器上,你只需要按遥控器上简单的按钮就可以控制电视、空调等电器开关。

1、电视、空调等电器就是不同的子系统。

2、遥控器是外观类,它将电视、空调的开关简单封装起来,提供了简单的接口(按钮)。

3、用户(客户端)只需要按遥控器的按钮,而不需要去操作每一个电器的开关。

4、如果需要替换一个新的电视,只要修改遥控器上的电视按钮对应代码,对客户端无影响。这样通过遥控器(外观类)把复杂的子系统简化和封装起来,用户就只需要操作简单的接口,大大降低了系统的复杂性。同时在修改子系统时,也只会影响外观类而不会影响到客户端。

总之,外观模式提供了一个简单入口来访问和使用复杂子系统,它对客户屏蔽了子系统组件,减少系统相互依赖,实现解耦。

假设现在有一个简单的例子:平日我们网上购物一般会分为4个步骤,挑选物品,添加购物车,填写收获信息和支付,下面我们就通过代码来实现上述功能。

定义一个网上购物的流程接口:

public interface PurchaseProcess {

    //挑选物品
    void pickGoods(String goodName);

    //添加到购物车
    void addCart(String goodName);

    //填写收货信息
    void addConsigneeInformation(String consigneeInformation);

    //支付
    void pay();


}

购物接口对应的实现类:

public class PurchaseProcessImpl implements PurchaseProcess {
    @Override
    public void pickGoods(String goodName) {
        System.out.println("挑选的商品:"+goodName);
    }

    @Override
    public void addCart(String goodName) {
        System.out.println("将《"+goodName+"》添加到购物车!");
    }

    @Override
    public void addConsigneeInformation(String consigneeInformation) {
        System.out.println("您填写的收货地址:"+consigneeInformation);
    }

    @Override
    public void pay() {
        System.out.println("支付完成...");
    }
}

提供一个统一的方法进行购物:

public class Shopping {

    private PurchaseProcessImpl purchaseProcess = new PurchaseProcessImpl();

    public void purchaseGoods(String goodName,String consigneeInformation) {
        purchaseProcess.pickGoods(goodName);
        purchaseProcess.addCart(goodName);
        purchaseProcess.addConsigneeInformation(consigneeInformation);
        purchaseProcess.pay();
    }
}

客户端:

public class Client{
    public static void main(String[] args) {
        Shopping shopping = new Shopping();
        shopping.purchaseGoods("华为Mate40 Pro","上海");
    }
}

运行结果如下:

如果需要添加支付方式呢,我们还需要重新设计购买的步骤,具体的代码实现如下:

定义一个支付方式实现类: 

public class PayMode {
    public void payMode(String payMode){
        System.out.println("支付方式:"+payMode);
    }
}

改造购物方式方法中的代码,新增一个支付方式:

public class Shopping {

    private PurchaseProcessImpl purchaseProcess = new PurchaseProcessImpl();

    private PayMode mode = new PayMode();

    public void purchaseGoods(String goodName,String consigneeInformation,String payMode) {
        purchaseProcess.pickGoods(goodName);
        purchaseProcess.addCart(goodName);
        purchaseProcess.addConsigneeInformation(consigneeInformation);
        mode.payMode(payMode);
        purchaseProcess.pay();
    }
}

客户端:

public class Client{
    public static void main(String[] args) {
        Shopping shopping = new Shopping();
        shopping.purchaseGoods("华为Mate40 Pro","上海","支付宝");
    }
}

运行结果如下:

五、总结

优点:

1、减少系统相互依赖:外观模式使得客户端和子系统的复杂关系放在外观类中,外界仅需面对一个简单的外观类,大大降低了客户与子系统间的耦合关系。

2、提高灵活性:通过引入外观类,可以在不影响其他子系统的情况下修改子系统。

3、更好的层次结构:外观模式可以更好地定义系统不同层次的功能

缺点:

1、不符合开闭原则。如果需要修改外观类,有可能需要修改所有客户端代码。

使用场景:

1、提供一个简单的接口以屏蔽子系统组件的复杂性。

2、在层次化结构中定义入口点。

符合的设计原则:

1 依赖倒转原则(Dependence Inversion Principle)

外观类与子系统之间形成了一种逆向的依赖关系,外观类依赖于抽象接口,而子系统则实现这些抽象接口,这个依赖关系是倒置的,降低了外观类与子系统的耦合度。

2 迪米特法则(Law of Demeter)

外观类与子系统之间遵循最小知识原则,外观类只与需要交互的子系统直接通信,而不关心子系统内部的实现细节,降低了耦合度。

简单来说,外观模式通过提供一个高层接口来封装细节,简化子系统使用,使子系统之间解耦,它提高了程序的灵活性和可维护性。 

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

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

相关文章

自动驾驶与智能网联场地测试一体化装备应用

自动化驾驶层级与结构 L1:能够辅助驾驶员玩车某些驾驶任务制动防抱死系统 (ABS),车身电子稳定系统 (ESP)等,这些配置就是L1级别的运用。 L2:部分自动化,在L2的级别里,必须要具备的是自适应巡航系统,主动车道保持系统自动刹车辅助系统以及自动泊车系统等系统。 L3:有条件…

JavaWeb(2)——HTML、CSS、JS 快速入门

一、JavaScript快速入门 一个完整的JavaScript实现由3个不同部分组成:核心(ECMAScript)、文档对象模型(DOM)和浏览器对象模型(BOM),如图所示。 ECMAScript是一种通过ECMA-262标准化…

iview table选中项显示在上方tag标签并可以取消

如图表格多选功能选中项显示在table的上方并且支持跨页&#xff0c;table上方加tag标签 <spanclass"select_tips"><Tagv-for"item in selection":key"item.id":name"item.id"closableon-close"handleClose">{{…

Python GUI编程利器:Tkinker中的消息对话框(13)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日目标 学习Tkinter中的消息对话框的使用&#xff0c;实现如下效果&#xff1a; 文本消息对话框 可以通过showinfo()创建文…

AtcoderABC258场

A - When? A - When? 题目大意 给定一个整数K&#xff0c;表示从日本标准时间21:00开始经过的分钟数。要求将该时间转换为24小时制的时间&#xff08;HH:MM格式&#xff09;。 思路分析 可直接分时间打印。关于格式&#xff0c;填充0&#xff0c;打印时间&#xff0c;题解…

DP83TG720RWRHARQ1汽车以太网PHY,NTHL020N120SC1 通孔 N-CH 1200V 103A(MOSFET)

DP83TG720RWRHARQ1汽车以太网PHY是一款符合IEEE 802.3bp和Open Alliance标准的汽车以太网物理层收发器。该器件通过屏蔽/屏蔽单双绞线提供传输和接收数据所需的所有物理层功能。该器件支持RGMII与MAC连接。 应用&#xff1a; 远程信息处理控制单元&#xff08;TCU、TBOX&#x…

接口测试 [分享] 自动化测试与持续集成方案--Jmeter 测试接口及性能

目录 前言&#xff1a; 一、什么是接口测试&#xff1f; 二、接口测试的流程 三、编写接口测试脚本 四、接口持续集成 补上性能测试报告&#xff1a; 前言&#xff1a; 接口测试是软件测试中的重要环节&#xff0c;它用于验证系统的不同组件之间的通信和数据传输是否正常…

一起学SF框架系列5.7-模块Beans-BeanDefinition使用

SF如何使用BeanDefinition达成其目标IoC&#xff0c;我们通过跟踪BeanDefinition使用来了解。 使用起点 跟踪SF初始化过程&#xff0c;第一个点在&#xff1a;DefaultListableBeanFactory.preInstantiateSingletons。如下图&#xff1a; RootBeanDefinition是运行时Spring B…

前端白屏检测方案

早期因为浏览器、技术、兼容性等诸多问题&#xff0c;导致网页的显示效果非常的单一&#xff0c;基本都是静态页&#xff0c;后续随着Angular、React、Vue等前端框架的出现&#xff0c;采用SPA单页面应用的方案越来越多。 用户和企业对于页面的稳定性、性能有了更高的诉求&…

openssl为什么从1.1跳跃到3.0,为什么没有2.0版本?

OpenSSL在版本号上从1.1跳跃到3.0是因为在其发展过程中发生了一些特定的情况和变化&#xff0c;导致开发团队做出了这样的决定。以下是一些可能的原因&#xff1a; 历史背景&#xff1a;OpenSSL的版本号体系并不是连续递增的&#xff0c;而是根据项目的发展和变化进行调整。在过…

UFS 15 - UFS RPMB操作

UFS 15 - UFS RPMB操作 1 Request Type Message Delivery&#xff08;请求类型消息传递&#xff09;2 Response Type Message Delivery&#xff08;响应类型消息传递&#xff09;3 Authentication Key Programming3.1 Authentication Key Programming3.2 报文示例3.2.1 Authent…

【工具使用】使用J-link离线下载芯唐MCU固件

一&#xff0c;简介 本文主要介绍如何使用J-link工具&#xff0c;离线下载M483的程序。 二&#xff0c;操作步骤 主要分为以下三个步骤&#xff1a; 1&#xff0c;使用SWD接口连接硬件&#xff1b; 2&#xff0c;配置上位机工程&#xff1b; 3&#xff0c;下载程序到芯片&am…

LiveGBS流媒体平台GB/T28181功能-作为上级平台对接海康大华华为宇视等下级平台监控摄像机NVR硬件执法仪等GB28181设备

LiveGBS作为上级平台对接海康大华华为宇视等下级平台监控摄像机NVR硬件执法仪等GB28181设备 1、背景说明2、部署国标平台2.1、安装使用说明2.2、服务器网络环境2.3、信令服务配置 3、监控摄像头设备接入3.1、海康GB28181接入示例3.2、大华GB28181接入示例3.3、华为IPC GB28181接…

图像处理之比特平面分层和重构

一、比特平面分层 像素是由比特组成的数字。例如在256级灰度图像中&#xff0c;每个像素的灰度是由8比特&#xff08;一个字节&#xff09;组成。如下图所示&#xff0c;一幅8比特图像由8个1比特平面组成&#xff0c;其中平面1包含图像中所有像素的最低阶比特&#xff0c;而平…

Linux开发工具gdb篇

文章目录 &#x1f3bb;0.前言&#x1f3bc;debug版本&#x1f3bc;release版本 &#x1fa95;1. gcc/g的默认版本&#x1f3b8;2. gdb使用&#x1f3b5;进入 & 退出&#x1f3b5;查看代码&#x1f3b5;断点 & 跳断点&#x1f3b5;逐过程 & 逐语句&#x1f3b5;监视…

Spring Boot 核心运行原理介绍

Spring Boot 核心运行原理介绍 引言整体介绍1. 核心运行原理图2. 自动配置的整体流程3. 各核心功能和组件初步介绍 总结 引言 还记得&#xff0c;笔者在前面的博文《Spring Boot 项目介绍》中提到了&#xff0c;Spring Boot 最核心的功能就是自动配置&#xff0c;该功能的实现…

编辑距离算法(Levenshtein Distance Algorithm)的概念理解及其应用

概念&#xff1a; 编辑距离&#xff0c;由俄罗斯科学家Vladimir Levenshtein于1965年提出&#xff0c;因此又称为Levenshtein Distance&#xff0c;简称LD&#xff0c;是指两个字串之间&#xff0c;由一个转成另一个所需的最少编辑操作次数。 可用的编辑操作包括&#xff1a;…

使用docker的常见bug

BUG1&#xff1a;磁盘被占满导致docker无法使用 docker ps 【查看docker能否正常使用】 正常的话会打印下图信息: 不正常的话打印如下图信息&#xff1a; journalctl -u docker 【查看docker无法正常使用的原因】&#xff0c;本次测试中遇到下图bug&#xff0c;意思是/var/l…

短视频抖音seo矩阵源码saas--技术开发部署分享

抖音seo源码开发&#xff0c;抖音矩阵源码&#xff0c;短视频seo源码&#xff0c;短视频矩阵源码技术开发部署&#xff0c;模式采用SaaS形式&#xff0c;用户角色分为&#xff1a;总后台&#xff0c;加盟商&#xff0c;企业用户&#xff0c;角色权限划分清楚&#xff0c;多模式…

简单认识MySQL基础部分

文章目录 一、数据库概述1、简介2、数据库类型和常用数据库1.关系型数据库2.非关系型数据库 3、mysql数据库日志1、作用&#xff1a;2、 mysql与 oracle 日志有所区别3、 Mysql 存储引擎 二、数据库基础操作1、SQL 语句2、实际操作1、DDL&#xff1a;数据定义语言&#xff0c;用…