【结构型】树形结构的应用王者,组合模式

news2024/9/20 18:34:10

在这里插入图片描述

目录

    • 一、组合模式
      • 1、组合模式是什么?
      • 2、组合模式的主要参与者:
    • 二、优化案例:文件系统
      • 1、不使用组合模式
      • 2、通过组合模式优化上面代码
        • 优化点:
    • 三、使用组合模式有哪些优势
      • 1、统一接口,简化客户端代码
      • 2、递归结构处理方便
      • 3、易扩展
      • 4、简化客户端操作
      • 5、动态组合灵活
    • 四、适用场景
    • 五、组合模式的劣势
    • 六、在jdk源码中,哪些地方应用了组合模式,代码举例说明一下
      • 1、AWT(Abstract Window Toolkit)中的组件树
        • (1)代码分析:
        • (2)JDK 源码中的示例(简化):
        • (3)组合模式分析:
      • 2、集合框架中的 java.util 包
        • (1)代码分析:
        • (2)JDK 源码中的示例:
        • (3)组合模式分析:
      • 3、小总结
    • 七、总结
      • 在这里,直接用 OpenAI o1草莓大模型

在日常开发中,我们往往忽视了设计模式的重要性。这可能是因为项目时间紧迫,或者对设计模式理解不深。其实,很多时候我们可能在不经意间已经使用了某些模式。

重要的是要有意识地学习和应用,让代码更加优雅和高效。也许是时候重新审视我们的编程实践,将设计模式融入其中了。

今天由浅入深,重学【组合模式】,让我们一起“重学设计模式”。

一、组合模式

1、组合模式是什么?

组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得用户可以像使用单个对象一样使用对象组合,简化了复杂结构的处理。

2、组合模式的主要参与者:

  1. Component(抽象组件):定义了对象的接口,所有组合对象和叶子节点都应实现它。
  2. Leaf(叶子节点):表示没有子节点的对象,即树的末端。
  3. Composite(组合对象):表示拥有子节点的对象。它不仅实现了 Component 接口,还能够存储并管理其子节点。

二、优化案例:文件系统

文件系统是组合模式的经典案例。文件系统中的文件夹可以包含文件或其他文件夹。无论是文件还是文件夹,它们都应该有一些共同的行为,例如显示名称或计算大小。

1、不使用组合模式

如果不采用组合模式,代码将需要分别处理叶子节点(如文件)和组合对象(如文件夹),这会导致代码复杂性增加。没有统一的接口意味着文件和文件夹需要不同的处理逻辑,导致代码的重复和不易扩展。

每次添加新的文件类型或子文件夹时,都需要修改已有代码,增加文件和文件夹的处理逻辑,代码会变得难以维护和扩展。

  1. 冗余代码:Folder 类中有两个集合,一个存储文件,另一个存储子文件夹。由于没有通用接口,必须为文件和文件夹分别编写逻辑。
  2. 缺乏一致性:要操作文件和文件夹时,必须分别对待。例如,showDetails() 方法中,文件和文件夹需要分开处理,无法将它们统一成一个对象。
  3. 扩展性差:如果将来想要添加新的类型,比如符号链接、压缩文件等,必须分别为它们定义类,并在每个相关的逻辑中添加处理它们的代码。
public class File {

    private String name;
    private int size;

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    public void showDetails() {
        System.out.println("File: " + name + " (Size: " + size + " KB)");
    }
}

public class Folder {
    private String name;
    private List<File> files = new ArrayList<>();
    private List<Folder> subFolders = new ArrayList<>();

    public Folder(String name) {
        this.name = name;
    }

    public void addFile(File file) {
        files.add(file);
    }

    public void addFolder(Folder folder) {
        subFolders.add(folder);
    }

    public void showDetails() {
        System.out.println("Folder: " + name);

        // 显示文件夹中的文件
        for (File file : files) {
            file.showDetails();
        }

        // 递归显示子文件夹中的内容
        for (Folder folder : subFolders) {
            folder.showDetails();
        }
    }
}

public class Test {

    public static void main(String[] args) {
        File file1 = new File("Document.txt", 50);
        File file2 = new File("Photo.jpg", 200);

        Folder folder = new Folder("MyFolder");
        folder.addFile(file1);
        folder.addFile(file2);


        File file3 = new File("test0.txt", 50);
        File file4 = new File("test1.jpg", 200);

        Folder folderRoot = new Folder("MyFolderRoot");
        folderRoot.addFile(file3);
        folderRoot.addFile(file4);

        folderRoot.addFolder(folder);

        folderRoot.showDetails();
    }
}

2、通过组合模式优化上面代码

在电子商务网站的产品目录中,可以通过组合模式管理产品和产品类别。每个产品(叶子节点)具有价格和描述,产品类别(组合对象)可以包含其他类别或产品。通过使用组合模式,可以简化查询价格、库存和类别层次的操作。

优化点:
  1. 简化层次结构:在系统中,产品与类别都遵循相同的接口,可以统一处理产品和类别。
  2. 灵活性:可以动态地增加或移除产品和类别,提高系统的可扩展性和维护性。

这个模式特别适合应用于具有递归或树形结构的场景。

文件和文件夹可以看作统一的组件,处理逻辑一致,新增类型时只需实现抽象接口,原有代码不需要修改。

/**
 * 抽象组件
 */
public abstract class FileSystemComponent {

    public abstract void showDetails();
}

/**
 * 叶子节点:文件
 */
public class File extends FileSystemComponent {

    private String name;
    private int size;

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public void showDetails() {
        System.out.println("File: " + name + " (Size: " + size + " KB)");
    }
}

/**
 * 组合对象:文件夹
 */
public class Folder extends FileSystemComponent {

    private String name;
    private List<FileSystemComponent> components = new ArrayList<>();

    public Folder(String name) {
        this.name = name;
    }

    public void addComponent(FileSystemComponent component) {
        components.add(component);
    }

    @Override
    public void showDetails() {
        System.out.println("Folder: " + name);
        for (FileSystemComponent component : components) {
            component.showDetails();
        }
    }
}

public class CombinationClient {
    public static void main(String[] args) {
        FileSystemComponent file1 = new File("Document.txt", 50);
        FileSystemComponent file2 = new File("Photo.jpg", 200);

        Folder folder = new Folder("MyFolder");
        folder.addComponent(file1);
        folder.addComponent(file2);

        File file3 = new File("test0.txt", 50);
        File file4 = new File("test1.jpg", 200);

        Folder folderRoot = new Folder("MyFolderRoot");
        folderRoot.addComponent(file3);
        folderRoot.addComponent(file4);

        folderRoot.addComponent(folder);

        folderRoot.showDetails();
    }
}

三、使用组合模式有哪些优势

1、统一接口,简化客户端代码

组合模式为对象和对象组合提供了统一的接口,客户端可以一致地操作单个对象和组合对象,而不必区分它们是叶子还是组合。这种一致性减少了处理不同类型对象的复杂度,简化了代码。

2、递归结构处理方便

组合模式特别适合处理树形或递归结构,如文件系统、组织结构等。通过递归调用,可以轻松遍历整个结构(无论是文件还是文件夹),不必写不同的处理逻辑。

3、易扩展

新增叶子节点或组合对象时,只需实现相同的接口,不需要修改已有的代码。组合模式具有开放-封闭原则的优势,使系统更加灵活、易于扩展。

4、简化客户端操作

客户端不再需要关心对象的具体类型(叶子或组合),只需处理抽象组件。这使得代码更加简洁,也减少了错误处理的复杂性。

5、动态组合灵活

通过组合模式,可以动态地组合对象,而无需预先定义复杂的类结构。这为复杂对象提供了灵活的处理方式,使得系统结构更具弹性。

四、适用场景

  1. 树形结构(层次结构): 组合模式非常适用于需要表示“部分-整体”关系的场景,尤其是树形结构。例如,文件系统、组织结构图、产品目录树、菜单系统等。
    • 文件系统:文件和文件夹之间的层次关系可以通过组合模式来轻松管理。无论是单个文件,还是包含子文件夹的文件夹,都可以通过相同的方式处理。
    • 组织结构图:公司中员工和部门之间存在层次结构,员工可以属于某个部门,部门可以属于其他部门,通过组合模式,可以方便地管理和展示这种结构。
  2. GUI控件(图形用户界面): GUI 组件经常包含其他组件,如按钮、窗口、面板等。组合模式可以用来管理这些图形控件,让它们统一处理。例如,一个窗口可能包含面板,面板中包含按钮和文本框,这些控件都可以通过相同的接口进行管理和渲染。
  3. 菜单系统: 菜单项可以包含子菜单,也可以是普通的菜单项。组合模式可以用于菜单系统的设计,使得菜单项和子菜单都实现相同的接口,从而简化菜单的显示和操作。
  4. 产品目录和分类管理: 电子商务网站中,产品可以属于某个类别,类别之间也有层次结构。组合模式可以用于管理产品和类别,通过统一接口可以轻松查询、操作或统计不同类别下的产品信息。
  5. 图形绘制系统: 在图形绘制系统中,复杂的图形可能是由多个简单图形组成的。组合模式允许将简单图形和复杂图形统一起来处理,方便实现图形的递归绘制和操作。
  6. 权限系统: 在权限管理中,角色和权限之间可能存在层次关系,一个角色可以拥有多个权限,权限可以包含子权限。组合模式可以用于简化权限系统的设计,使得权限的分配和管理更加灵活。
  7. 编译器中的抽象语法树(AST): 编译器在解析源代码时,会生成抽象语法树(AST),其中每个节点可以是语法结构的一个元素(如表达式、语句等)。通过组合模式,编译器可以对这些节点进行统一处理,而不需要关心它们的具体类型。

五、组合模式的劣势

虽然组合模式有很多优势,但它也有一些潜在的劣势:

  1. 过度抽象:为了实现通用接口,可能导致系统设计过于抽象和复杂,尤其是在层次结构非常深的情况下,增加了理解和维护的难度。
  2. 性能问题:由于组合模式需要递归处理对象结构,在大规模、深层次的树形结构中,递归操作可能带来性能问题。
  3. 类型安全问题:组合模式统一了叶子节点和组合对象的接口,有时可能难以强制类型检查。例如,某些操作只对叶子节点有效,调用这些操作时可能需要额外的类型判断。

六、在jdk源码中,哪些地方应用了组合模式,代码举例说明一下

在JDK源码中,组合模式被广泛应用于处理树形或层次结构的数据结构和设计,最典型的例子之一是 java.awt 包中的 Component 类,以及集合框架中的 java.util 包。

以下是两个常见的应用场景:

1、AWT(Abstract Window Toolkit)中的组件树

在 java.awt 包中,Component 类和 Container 类使用了组合模式。Container 代表可以包含子组件的对象,而 Component 是一个抽象组件,代表所有的 GUI 元素。Container 既可以是单个组件(叶子),也可以是组合组件(容器),从而形成了一个树形的 GUI 组件层次结构。

(1)代码分析:
  1. Component 类是所有 GUI 元素的基类。
  2. Container 类是 Component 的子类,它可以包含多个子组件。
(2)JDK 源码中的示例(简化):
// java.awt.Component
public abstract class Component {
    // 省略大量方法
    public void paint(Graphics g) {
        // 绘制组件的代码
    }
}

// java.awt.Container
public class Container extends Component {
    // 存储子组件
    private List<Component> componentList = new ArrayList<>();

    public void add(Component comp) {
        componentList.add(comp);
    }

    public void remove(Component comp) {
        componentList.remove(comp);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 递归调用子组件的 paint 方法
        for (Component comp : componentList) {
            comp.paint(g);
        }
    }
}
(3)组合模式分析:
  1. Component 是一个抽象类,定义了所有组件的通用接口。
  2. Container 是一个组合对象,包含其他组件,并可以递归地管理和绘制这些组件。
  3. 在使用时,GUI 系统可以统一处理 Component 对象,不论它是叶子组件(如按钮、文本框),还是组合组件(如面板、窗口)。

2、集合框架中的 java.util 包

在 Java 集合框架中,List、Set、Map 等接口也使用了组合模式。集合类中既有可以直接存储元素的类(如 ArrayList、HashSet),也有可以组合其他集合的类(如 Collections.unmodifiableList、Collections.synchronizedList 等)。

(1)代码分析:
  1. List 接口是所有列表的通用接口。
  2. ArrayList 实现了 List 接口,代表叶子节点,可以直接存储元素。
  3. Collections.unmodifiableList 通过组合模式,将一个已有的列表封装起来,实现不可修改的列表。
(2)JDK 源码中的示例:
// java.util.List (接口)
public interface List<E> extends Collection<E> {
    // 定义列表的通用方法
    boolean add(E e);
    E get(int index);
    // 省略其他方法
}

// java.util.ArrayList (叶子节点)
public class ArrayList<E> extends AbstractList<E> implements List<E> {
    private Object[] elementData;
    private int size;
    
    public ArrayList() {
        elementData = new Object[10];
    }

    @Override
    public boolean add(E e) {
        // 添加元素的逻辑
        elementData[size++] = e;
        return true;
    }

    @Override
    public E get(int index) {
        return (E) elementData[index];
    }
    // 省略其他方法
}

// java.util.Collections.unmodifiableList (组合对象)
public static <T> List<T> unmodifiableList(List<? extends T> list) {
    return new UnmodifiableList<>(list);
}

// 内部类,包装一个已有的 List
private static class UnmodifiableList<E> extends AbstractList<E> {
    private final List<? extends E> list;

    UnmodifiableList(List<? extends E> list) {
        this.list = Objects.requireNonNull(list);
    }

    @Override
    public E get(int index) {
        return list.get(index);
    }

    @Override
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
}

(3)组合模式分析:
  1. List 接口是抽象组件,定义了所有列表操作的通用方法。
  2. ArrayList 是具体的叶子节点,可以直接存储和操作元素。
  3. UnmodifiableList 是一个组合对象,它通过包装另一个 List 实现不可修改的列表,并且与其他 List 一样实现了 List 接口。
  4. List 和 ArrayList 之间的关系符合组合模式:ArrayList 作为叶子节点实现了通用的 List 接口,而 UnmodifiableList 通过组合其他列表来扩展功能,形成了一个树形的结构。

3、小总结

组合模式在 JDK 中的应用主要体现在处理层次结构、递归结构的场景。AWT 中的 Component 和 Container 类,集合框架中的 List 接口及其实现,都采用了组合模式。通过这种设计,Java 提供了灵活而统一的接口,简化了对复杂对象结构的处理,同时保持了系统的可扩展性。

七、总结

组合模式(Composite Pattern)是一种结构型设计模式,适用于将对象组合成树形结构来表示“部分-整体”的层次关系。它允许用户像使用单个对象一样操作对象组合,简化了复杂结构的处理。组合模式的主要参与者包括抽象组件(Component),叶子节点(Leaf),和组合对象(Composite)。每个组件通过统一接口,支持递归处理子节点,使得系统更加灵活、易扩展。

以文件系统为例,文件夹可以包含文件或其他文件夹。在不使用组合模式时,文件和文件夹必须分别处理,导致代码复杂性增加且扩展性差。通过组合模式,可以使用统一的接口管理文件和文件夹,简化层次结构并增强系统的扩展性和灵活性。

组合模式在JDK源码中有广泛应用,如 java.awt 中的组件树(Component 和 Container 类),以及集合框架中的 List、ArrayList 和 Collections.unmodifiableList。这些类通过组合模式处理递归结构和对象组合,使得操作统一、灵活。

在这里,直接用 OpenAI o1草莓大模型

谷歌浏览器访问:https://www.nezhasoft.cn

👉 GPT功能:

  1. GPT-4o知识问答:支持1000+token上下文记忆功能
  2. 最强代码大模型Code Copilot:代码自动补全、代码优化建议、代码重构等
  3. DALL-E AI绘画:AI绘画 + 剪辑 = 自媒体新时代
  4. 私信哪吒,直接使用GPT-4o


🏆文章收录于:100天精通Java从入门到就业

哪吒数年工作总结之结晶。

🏆哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

华为OD机试 2023B卷题库疯狂收录中,刷题点这里

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

点击下方名片,回复1024,获取《10万字208道Java经典面试题总结(2024修订版).pdf 》

在这里插入图片描述

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

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

相关文章

maxcompute使用篇

文章目录 maxcompute使用篇1.mongoDB与maxcompute 进行数据同步1.1 基本类型的数据1.2部分复杂类型的数据 2.maxcompute中复杂数据类型解析2.1 get_json_object2.2 json_tuple2.3 处理json几种失效的情况:2.4 STR_TO_MAP、MAP_KEYS2.5 regexp_replace2.6 FROM_JSON2.7 nvl2.8 t…

基于matlab的通信系统设计及仿真

文章目录 前言资料获取设计介绍功能介绍设计程序具体实现截图参考文献设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设…

PHP邮箱系统:从入门到实战搭建教程指南!

PHP邮箱系统配置教程&#xff1f;如何选用合适的PHP邮箱系统库&#xff1f; 为了满足个性化和定制化的需求&#xff0c;许多开发者选择使用PHP来搭建自己的邮箱系统。AokSend将带你从入门到实战&#xff0c;详细介绍如何搭建一个功能完善的PHP邮箱系统。 PHP邮箱系统&#xf…

谈谈你对线程池的了解

一、什么是线程池 线程池是一种创建和管理线程的技术。 二、怎么创建线程池 通过Executors工具类的静态方法&#xff0c;创建线程池。创建ThreadPoolExecutor对象&#xff0c;按照业务需要&#xff0c;自定义线程参数&#xff0c;创建线程池。 三、线程池的状态有哪些 线程池的…

VMware vCenter Server 8.0U3b 发布下载,新增功能概览

VMware vCenter Server 8.0U3b 发布下载&#xff0c;新增功能概览 Server Management Software | vCenter 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vcenter-8-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysi…

VirtualBox7.1.0 安装 Ubuntu22.04.5 虚拟机

环境 &#xff08;1&#xff09;宿主机系统&#xff1a;Windows10 &#xff08;2&#xff09;虚拟机软件&#xff1a;VirtualBox7.1.0 &#xff08;3&#xff09;虚拟机系统&#xff1a;Ubuntu 22.04.5 LTS (Jammy Jellyfish) 步骤 &#xff08;1&#xff09;第一步 &…

Python基础(七)——PyEcharts数据分析(面向对象版)

四、使用PyEcharts数据分析案例&#xff08;面向对象版&#xff09; 【前言&#xff1a;为了巩固之前的Python基础知识&#xff08;一&#xff09;到&#xff08;五&#xff09;&#xff0c;并为后续使用Python作为数据处理的好帮手&#xff0c;我们一起来用面向对象的思想来理…

并发编程 - 锁(@synchronized)

引言 在前面的博客中&#xff0c;我们已经讨论了锁在多线程编程中的重要性&#xff0c;主要是为了解决多线程同时访问同一片共享数据时发生的竞争条件&#xff08;race conditions&#xff09;&#xff0c;导致数据不一致和崩溃问题。 并且介绍了一个在Objective-C中&#xf…

mysql笔记7(单表查询)

文章目录 1. select① 从伪表里查数据(可以结合第3点dual理解数据来源)select 文字 ;做计算&#xff1a;select 算式;select 文字( 或算式) as 别名;(as 用于起别名&#xff0c;可省略) ② 从真实表里查数据select * from 表名;select 字段名&#xff0c;字段名 from 表名; 2. …

centos远程桌面连接windows

CentOS是一款广泛使用的Linux发行版&#xff0c;特别是在服务器领域。很多企业和个人用户会选择远程连接到CentOS进行操作和维护。虽然CentOS自带了一些远程桌面解决方案&#xff0c;但它们在使用上存在一些局限性。接下来&#xff0c;我将介绍如何实现CentOS的远程桌面连接&am…

关于wordPress中的用户登录注册等问题

前言 大家在做类似的功能的时候&#xff0c;有没有相关的疑问。那就是我都已经选择好了相应的主题和模版&#xff0c;但是为什么都没有用户注册和用户登录的页面存在呢&#xff1f; WordPress默认情况下不提供用户注册和登录功能的原因是它最初是作为一个博客平台开发的&…

OCR两篇革命之作

DocOwl2 参考 阿里8B模型拿下多页文档理解新SOTA&#xff0c;324个视觉token表示一页&#xff0c;缩减80% mPLUG-DocOwl 2聚焦多页文档理解&#xff0c;兼顾效果和效率&#xff0c;在大幅缩减单页视觉token的前提下实现了多页文档理解的SOTA效果。 仅用324个token表示文档图…

离散制造 vs 流程制造:锚定精准制造未来,从装配线到化学反应,实时数据集成在制造业案例中的多维应用

使用 TapData&#xff0c;化繁为简&#xff0c;摆脱手动搭建、维护数据管道的诸多烦扰&#xff0c;轻量替代 OGG, Kettle 等同步工具&#xff0c;以及基于 Kafka 的 ETL 解决方案&#xff0c;「CDC 流处理 数据集成」组合拳&#xff0c;加速仓内数据流转&#xff0c;帮助企业…

使用雷达速度因子进行越野导航的鲁棒高速状态估计

使用雷达速度因子进行越野导航的鲁棒高速状态估计 Morten Nissov 1 , 2 ^{1,2} 1,2, Jeffrey A. Edlund 1 ^{1} 1, Patrick Spieler 1 ^{1} 1, Curtis Padgett 1 ^{1} 1, Kostas Alexis 2 ^{2} 2 和 Shehryar Khattak 1 ^{1} 1 摘要 在复杂环境中实现机器人自主性以用于关键…

【限流算法】

文章目录 介绍算法原理适用场景令牌通算法实现限流算法 介绍 令牌桶算法是网络流量整形&#xff08;Traffic Shaping&#xff09;和速率限制&#xff08;Rate Limiting&#xff09;中最常使用的一种算法。典型情况下&#xff0c;令牌桶算法用来控制发送到网络上的数据的数目&a…

第6天:趋势轮动策略开发(年化18.8%,大小盘轮动加择时)

原创内容第655篇&#xff0c;专注量化投资、个人成长与财富自由。 轮动策略是一种投资策略&#xff0c;它涉及在不同的资产类别、行业或市场之间进行切换&#xff0c;以捕捉市场机会并优化投资组合的表现。 这种策略的核心在于识别并利用不同资产或市场的相对强弱&#xff0c…

[数据集][目标检测]智慧养殖场肉鸡目标检测数据集VOC+YOLO格式3548张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3548 标注数量(xml文件个数)&#xff1a;3548 标注数量(txt文件个数)&#xff1a;3548 标注…

医学数据分析实训 项目九 糖尿病风险预测

文章目录 综合实践二 糖尿病遗传风险预测一、分析目标二、实现步骤三、数据准备四、特征工程五、模型构建六、性能度量七、提交要求 综合实践任务二 糖尿病遗传风险预测代码&#xff08;一&#xff09;数据准备&#xff08;二&#xff09;特征工程&#xff08;三&#xff09;模…

Selenium通过ActionBuilder模拟鼠标操作直接移动到指定坐标的注意事项

在目前&#xff08;2024-09-18&#xff09;得Selenium官方手册中&#xff0c;模拟鼠标操作基本上都是通过ActionChains完成的&#xff0c;唯独有一动作&#xff0c;是通过ActionBuilder完成的。 而前者ActionChains&#xff0c;主要是通过offset&#xff0c;也就是坐标偏移量来…

【Prometheus】jmx_prometheus_javaagent监控java应用

目录 一、概述 1.1 promethues简介 1.2 JMX Exporter简介 二、监控SparkHistoryServer实现 一、概述 1.1 promethues简介 promethues采集数据的方法很多&#xff0c;常用的是通过各种exporter去主机采集&#xff0c;然后有些程序是没有相关的exporter,所以有些时候会通过脚…