当前位置: 首页 > article >正文

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

文章目录

  • 引言
  • 组合模式简介
    • 定义与用途:
    • 实现方式
    • 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.kler.cn/news/161474.html

相关文章:

  • hql面试题之字符串使用split分割,并选择其中的一部分字段的问题
  • /usr/bin/ld: cannot find -ltinfo 的解决方法
  • 第二十一章——网络通信
  • 使用Jython将Python代码转换为Java可执行文件
  • 手把手将Visual Studio Code变成Python开发神器
  • RabbitMQ 的七种消息传递形式
  • 结构体对齐和补齐
  • HarmonyOS开发(十):通知和提醒
  • 洛谷P1044 [NOIP2003 普及组] 栈 递归方法
  • JVM中 Minor GC 和 Full GC 的区别
  • React中的空标签与Fragment标签的区别
  • 【数据库设计和SQL基础语法】--表的创建与操作--插入、更新和删除数据
  • Nginx(配置SLL证书)
  • 重生奇迹mu武器镶嵌顺序
  • MySQL学习day05
  • C++ STL容器与常用库函数
  • 一则广告,一个故事,这就我选择学习计算机专业的两个原因
  • 中国证券交易所有哪些
  • vs2022 winform 使用LiveCharts.Wpf控件出现黑框 去除方法
  • zabbix分布式监控平台从IPV4切换到IPV6之监控主机切换
  • 【LeeCode】1.两数之和
  • webpack配置scss loader
  • 【数据库】基于时间戳的并发访问控制,乐观模式,时间戳替代形式及存在的问题,与封锁模式的对比
  • 单片机学习13——串口通信
  • 在 Windows 桌面的redis中远程连接到 VMware 中运行的 Linux 上的 Redis
  • simulinkDFIG风电场风机并网渗透率系统稳定性小信号特征值分析,特征根轨迹分析。四机两区域模型系统
  • 基于B/S架构的医院一体化电子病历编辑器源码
  • Docker的数据卷
  • 使用ApexSQLLog工具恢复数据库
  • 【C语言快速学习基础篇】之一基础类型、进制转换、数据位宽