java设计模式学习之【组合模式】

news2025/2/24 7:44:35

文章目录

  • 引言
  • 组合模式简介
    • 定义与用途:
    • 实现方式
    • UML
  • 使用场景
  • 优势与劣势
  • 组合模式在Spring中的应用
  • 员工结构示例
  • 代码地址

引言

设想您正在组织一个大型派对,需要将各种食品和饮料按类型整理。您可能有单独的物品,如一瓶苏打水,也可能有物品的集合,如一篮子水果。无论是单个苏打水瓶还是一整篮水果,您都希望以同样的方式处理它们——放在合适的位置以便客人轻松获取。在软件设计领域,这种需要同时处理单个对象和对象集合的场景非常普遍。组合模式正是为了简化这类问题而生,它允许我们以统一的方式处理单个对象和对象的组合。

组合模式简介

组合模式是一种结构型设计模式,它使我们能够将对象组合成树形结构来表示整体与部分的层次关系。这种模式创建了一个包含自己对象组的类,这些对象可以是相似的类的实例,或者是完全不同的类的对象。使用组合模式,我们可以对单个对象和组合对象进行相同的操作,这大大简化了客户端代码。

定义与用途:

  • 组合模式使得单个对象和组合对象的使用具有一致性。
  • 它广泛应用于需要表示对象的部分-整体层次结构的场合。

实现方式

  • 定义一个表示节点和叶子节点的共同接口。
  • 创建一个类表示节点的组合,这个类可以包含其他节点或叶子节点。
  • 在组合类中实现共同接口的方法,并将这些方法的实现委托给相应的子节点。

UML

在这里插入图片描述
组合模式的四个主要元素:

组件(Component):
定义了组合中所有对象的共有接口。
实现了接口中对所有类通用的默认行为。
声明了访问和管理其子组件的接口。

叶子(Leaf):
在组合中代表没有子组件的叶子对象。
定义了组合中原始对象的行为。

复合体(Composite):
定义了拥有子组件的组件的行为。
存储子组件。
在组件接口中实现与子组件相关的操作。

客户端(Client):
通过组件接口操纵组合中的对象。

使用场景

  • 图形编辑器: 在一个图形编辑器中,你可能有形状(如圆形、矩形)和它们的组合(如图表)。组合模式可以用来统一处理单个形状和形状的组合。

  • 文件系统: 在文件系统中,文件和文件夹可以通过组合模式表示。文件夹可以包含文件和其他文件夹,但对用户来说,它们的使用方式是一致的。

  • UI 组件: 在用户界面设计中,简单组件(如按钮、文本框)和复合组件(如面板、窗口)都可以用组合模式来管理。

  • 组织结构: 在表示公司或其他组织的层次结构时,组合模式允许以统一的方式处理单个员工和部门。

  • 菜单系统: 在软件应用中的菜单系统,其中菜单项既可以是单个命令,也可以是包含其他菜单项的子菜单。

优势与劣势

  • 优势
    明确的层次结构:组合模式清晰地定义了部分和整体的层次关系。
    简化客户端代码:客户端可以统一地对待组合对象和单个对象。
    更容易增加新类型的组件:组合模式使得更改和增加新的元素类型变得更容易。
  • 劣势
    设计变得更加抽象:组合模式使得设计变得更加复杂,特别是你需要遍历一个组合对象的组成部分时。
    不容易限制组件的类型:在组合中很难限制组件的类型,因为它们通常共有相同的接口。

组合模式在Spring中的应用

组合模式在Spring框架中的应用体现在它如何管理和配置大量的Bean定义,以及如何处理资源文件。以下是Spring中使用组合模式的几个关键例子:

1. BeanDefinition
在Spring中,BeanDefinition是一个接口,代表了Bean的配置元数据。它是Spring管理Bean生命周期的核心部分。BeanDefinition对象可以被视为组合模式中的叶子节点,它们被组合在一起形成一个完整的Spring配置。
Composite Pattern Application: Spring容器通过将这些BeanDefinition对象组合在一起,形成了一个可管理的Bean配置集合。这允许Spring容器以统一的方式处理单个Bean和Bean集合,同时也使得添加新的Bean或组合现有Bean变得更加灵活和简单。

2. Resource
Spring的Resource接口是处理不同类型资源的抽象,如文件系统资源、类路径资源、URL资源等。它提供了统一的方式来访问这些资源。
Composite Pattern Application: 在Spring中,Resource接口的不同实现类似于组合模式中的叶子节点。Spring使用这些Resource对象来统一处理单个资源和资源集合。这种方式简化了资源访问的客户端代码,并使得资源处理更加灵活。

3. ApplicationContext
ApplicationContext是一个更高级的容器,它不仅包括了BeanFactory的所有功能,还加入了对事件传播、资源加载等更高级特性的支持。在Spring中,ApplicationContext本身也是一个大型工厂,用于创建并管理应用程序中的beans,以及提供对不同类型的bean的访问。
Composite Pattern Application: ApplicationContext可以视为一个组合对象,它管理和组合了多个BeanFactory和其他资源,如消息资源、事件处理器等。这提供了统一的方式来处理整个应用程序的配置和资源管理。

员工结构示例

在这里插入图片描述
步骤 1: 创建员工公共接口。

public interface Employee {

    public void showEmployeeDetails();

}

步骤 2: 具体员工实现类,开发,管理者。

public class Developer implements Employee{
    private String name;
    private long empId;
    private String position;

    public Developer(long empId, String name, String position) {
        // 分配员工 ID、姓名和职位
        this.empId = empId;
        this.name = name;
        this.position = position;
    }

    @Override
    public void showEmployeeDetails() {
        System.out.println(empId + " " + name + " " + position);
    }
}

public class Manager implements Employee{

    private String name;
    private long empId;
    private String position;

    public Manager(long empId, String name, String position) {
        this.empId = empId;
        this.name = name;
        this.position = position;
    }

    @Override
    public void showEmployeeDetails() {
        System.out.println(empId + " " + name + " " + position);
    }

}

步骤 3: 公司组织类,实现员工接口

public class CompanyDirectory implements Employee{

    private List<Employee> employeeList = new ArrayList<Employee>();

    @Override
    public void showEmployeeDetails() {
        for (Employee emp : employeeList) {
            emp.showEmployeeDetails();
        }
    }

    public void addEmployee(Employee emp) {
        employeeList.add(emp);
    }

    public void removeEmployee(Employee emp) {
        employeeList.remove(emp);
    }

}

步骤 4: 驱动测试

public class Company {

    public static void main(String[] args) {
        Developer dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer");
        Developer dev2 = new Developer(101, "Vinay Sharma", "Developer");
        CompanyDirectory engDirectory = new CompanyDirectory();
        engDirectory.addEmployee(dev1);
        engDirectory.addEmployee(dev2);

        Manager man1 = new Manager(200, "Kushagra Garg", "SEO Manager");
        Manager man2 = new Manager(201, "Vikram Sharma", "Kushagra's Manager");

        CompanyDirectory accDirectory = new CompanyDirectory();
        accDirectory.addEmployee(man1);
        accDirectory.addEmployee(man2);

        CompanyDirectory directory = new CompanyDirectory();
        directory.addEmployee(engDirectory);
        directory.addEmployee(accDirectory);
        directory.showEmployeeDetails();
    }

}

在这里插入图片描述

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

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

相关文章

您知道计算机是怎么分类的嘛

地表最强计算机 第 61 版全球最强大的超级计算机已经发布。名为 Top500&#xff0c;顾名思义&#xff0c;该列表列出了全球 500 台最强大的超级计算机。榜单显示&#xff0c;美国的AMD、英特尔和IBM处理器是超级计算系统的首选。在 TOP10 中&#xff0c;有四个系统使用 AMD 处理…

JWT安全及WebGoat靶场

JWT 安全 cookie(放在浏览器) cookie 是一个非常具体的东西&#xff0c;指的就是浏览器里面能永久存储的一种数据&#xff0c;仅仅是浏览器实现的一种数据存储功能。 cookie 由服务器生成&#xff0c;发送给浏览器&#xff0c;浏览器把 cookie 以 kv 形式保存到某个目录下的…

1+x网络系统建设与运维(中级)-练习题4

一.设备命名 LSW1 <Huawei>sys [Huawei]sysn LSW1 [LSW1]un in en 同理可得&#xff0c;给所有设备如以上命令一样配置 二.VLAN LSW1 [LSW1]vlan ba 1 10 20 100 [LSW1]int g0/0/1 [LSW1-GigabitEthernet0/0/1]port link-type trunk [LSW1-GigabitEthernet0/0/1]port tru…

axios调接口传参特殊字符丢失的问题(encodeURI 和 encodeURIComponent)

1、axios调接口特殊字符丢失的问题 项目开发过程中遇到一个接口传参&#xff0c;参数带特殊字符&#xff0c;axios调接口特殊字符丢失的问题 例如接口&#xff1a; get/user/detail/{name} name是个参数直接调接口的时候拼到接口上&#xff0c;get/user/detail/test123#$%&am…

记一次Java内存溢出导致程序宕机的问题及排查

Hi, I’m Shendi 记一次Java内存溢出导致程序宕机的问题及排查 问题场景 今天在使用工具中的 word 转 pdf 出了问题&#xff0c;报502错误&#xff0c;打开服务器发现服务被关闭了&#xff0c;起初以为是误关&#xff0c;打开后重新转换又出现了这个问题&#xff0c;在项目文件…

微信机器人接口开发

简要描述&#xff1a; 设置http回调地址 请求URL&#xff1a; http://域名地址/setHttpCallbackUrl POST 请求头Headers:&#xff08;别忘了传&#xff09; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必…

【尘缘送书第五期】Java程序员:学习与使用多线程

目录 1 多线程对于Java的意义2 为什么Java工程师必须掌握多线程3 Java多线程使用方式4 如何学好Java多线程5 参与方式 摘要&#xff1a;互联网的每一个角落&#xff0c;无论是大型电商平台的秒杀活动&#xff0c;社交平台的实时消息推送&#xff0c;还是在线视频平台的流量洪峰…

【Java 基础】23 国际化

文章目录 1.概念2.原理1&#xff09;Locale2&#xff09;ResourceBundle3&#xff09;MessageFormat 3.例子1&#xff09;准备资源文件2&#xff09;加载资源文件3&#xff09;格式化消息&#xff08;非必须&#xff09; 总结 在全球化的今天&#xff0c;开发支持多语言的应用变…

配置BFD状态与接口状态联动示例

1、BFD检测IP链路。 在IP链路上建立BFD会话&#xff0c;利用BFD检测机制快速检测故障。BFD检测IP链路支持单跳检测和多跳检测&#xff1a; BFD单跳检测是指对两个直连系统进行IP连通性检测&#xff0c;“单跳”是IP链路的一跳。 BFD多跳检测是指BFD可以检测两个系统间的任意路…

每日一练:插入排序

1. 概念及原理 插入排序是一种简单直观的排序算法&#xff0c;其基本思想是将一个元素插入到已经排序好的部分&#xff0c;然后不断地重复这个过程&#xff0c;直到整个数组有序。下面是插入排序的算法原理&#xff1a; 初始状态&#xff1a; 数组被分为已排序和未排序两个部分…

论文阅读——Deformable ConvNets v2

论文&#xff1a;https://arxiv.org/pdf/1811.11168.pdf 代码&#xff1a;https://github.com/chengdazhi/Deformable-Convolution-V2-PyTorch 1. 介绍 可变形卷积能够很好地学习到发生形变的物体&#xff0c;但是论文观察到当尽管比普通卷积网络能够更适应物体形变&#xff…

Python中如何判断List中是否包含某个元素

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python中&#xff0c;判断一个列表&#xff08;List&#xff09;是否包含某个特定元素是常见的任务之一。在本文中&#xff0c;将深入探讨多种判断List成员包含性的方法&#xff0c;并提供丰富的示例代码&…

Scratch少儿编程系统开发时案例验证的必要性

scratch少儿编程[1] 随着少儿编程教育的普及&#xff0c;越来越多的公司和集成商开始关注scratch少儿编程系统的二次开发。scratch是一个由麻省理工学院媒体实验室开发的免费、开源的少儿编程软件。它具有易用、趣味性强、可扩展性强等特点&#xff0c;非常适合少儿编程教育。…

产品成本收集器流程演示

感谢大佬的文章&#xff0c;我只是一个翻译搬运工&#xff0c;原文地址&#xff1a;产品成本收集器 概述 SAP 令人兴奋的部分之一是它在不同操作模块之间的集成程度。使用产品成本收集器来跟踪生产就是一个很好的例子。在本博客中&#xff0c;我计划遵循产品成本收集器流程&a…

分享一个微信红包封面过审方法

大家好&#xff0c;我是小悟 兄弟们&#xff0c;已经12月份了&#xff0c;今年的最后一个月&#xff0c;距离过年还有两个月左右&#xff0c;如果你需要制作微信红包封面&#xff0c;我建议你现在就可以着手了。 一方面&#xff0c;临近春节&#xff0c;会有很多人在制作红包封…

[b01lers2020]Life on Mars 一个接口的sql schema.schemate表

这里还是很简单的 啥也没有 然后抓包看看 发现传递参数 直接尝试sql 然后如果正确就会返回值 否则 返回1 chryse_planitia union select database(),version() 发现回显 直接开始注入 chryse_planitia union select database(),version()chryse_planitia union select data…

ESP32-Web-Server编程- 在 Web 上开发动态纪念册

ESP32-Web-Server编程- 在 Web 上开发动态纪念册 概述 Web 有很多有趣的玩法&#xff0c;在打开网页的同时送她一个惊喜。 需求及功能解析 本节演示在 ESP32 上部署一个 Web&#xff0c;当打开对应的网页时&#xff0c;将运行动态的网页内容&#xff0c;显示炫酷的纪念贺词…

linux学习之详解文件

目录 1.先认识文件 2.c语言中常用文件接口 fopen&#xff08;打开文件&#xff09; 3.系统接口操作文件 open write 文件的返回值以及打开文件的本质 理解struct_file内核对象 了解文件描述符&#xff08;fd&#xff09;分配规则 重定向 dup接口 标准错误流 文件缓冲…

【项目问题解决】IDEA2020.3 使用 lombok 插件 java: 找不到符号 符号: 方法 builder()

目录 lombok找不到符号问题修改 1.问题描述2.问题原因3.解决思路4.解决方案5.总结6.参考 文章所属专区 项目问题解决 1.问题描述 IDEA2020.3 使用 lombok 插件 java: 找不到符号 符号: 方法 builder()&#xff0c;无法使用lombok下应有的注解&#xff0c;一度怀疑是版本问题 …

二十一章(网络通信)

计算机网络实现了多台计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xff0c;相互之间可以交换数据。编写网络应用程序前&#xff0c;首先必须明确所要使用的网络协议…