【Java开发】设计模式 08:组合模式

1 组合模式介绍

组合模式是一种结构型设计模式,它允许将对象组合成树形结构,以表示部分-整体的层次结构。组合模式使得客户端可以统一处理单个对象和组合对象,从而简化了客户端代码。

在组合模式中,有两种类型的对象:叶子节点和组合节点。叶子节点表示树形结构中的最底层节点,它们不能再分解为更小的部分。组合节点表示树形结构中的中间节点和根节点,它们可以包含一个或多个子节点,这些子节点可以是叶子节点,也可以是其他的组合节点。

组合模式的核心思想是通过递归方式来遍历整个树形结构,从而实现对整体和部分的操作。客户端可以通过操作组合节点来操作整个树形结构,也可以通过操作叶子节点来操作单个对象。

📌 场景

  • 树形结构:当需要处理一个树形结构的对象集合时,可以使用组合模式。例如操作系统的文件系统,文件夹和文件的嵌套结构。

  • 命令模式:当需要执行一系列操作时,可以使用组合模式将这些操作组合成一个命令对象。例如文本编辑器中的撤销和重做功能。

  • 菜单和导航:当需要创建菜单和导航时,可以使用组合模式。例如网站的导航栏和下拉菜单。

  • 组合对象的属性:当需要对组合对象进行属性设置时,可以使用组合模式。例如在游戏中设计角色的属性,可以将角色的各个部分组合起来形成一个复合对象。

  • 组合对象的操作:当需要对组合对象进行操作时,可以使用组合模式。例如在图形编辑器中,可以对多个图形对象进行组合操作,包括平移、旋转、缩放等。

📌 优缺点

  • 优点:简化客户端代码、统一处理单个对象和组合对象、方便增加新的节点类型、提高代码复用性和可维护性等;

  • 缺点:可能会导致设计过度复杂,不适合处理复杂的逻辑。

2 组合模式实现

以目录和文件为例:

📌 1.定义组件

/**
 * 组件
 */
public abstract class Component {
    /**
     * 添加子组件
     * @param component 组件
     */
    public abstract void add(Component component);
    /**
     * 删除子组件
     * @param component 组件
     */
    public abstract void remove(Component component);
    /**
     * 获取子组件
     * @param index 组件序号
     * @return 子组件
     */
    public abstract Component getChild(int index);
    /**
     * 修改名称
     */
    public abstract void editName();
}

📌 2.定义目录

/**
 * 目录
 * <p>目录可以包含多个文件或目录
 */
public class Directory extends Component{
    /**
     * 使用 List 来存放目录中的子组件
     */
    List<Component> child = new ArrayList<>();

    @Override
    public void add(Component component) {
        child.add(component);
    }

    @Override
    public void remove(Component component) {
        child.remove(component);
    }

    @Override
    public Component getChild(int index) {
        return child.get(index);
    }

    @Override
    public void editName() {
        // 继续调用所有子组件的 editName 方法执行业务
        child.forEach(Component::editName);
    }
}

📌 3.定义文件

/**
 * 文件
 */
public class File extends Component{

    @Override
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Component getChild(int index) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void editName() {
        // 具体的名称修改操作
        System.out.println("修改文件:" + this);
    }
}

📌 4.调用

// 新建一个外层目录
Directory out = new Directory();
// 新建一个内层目录
Directory in = new Directory();
// 外层目录添加文件
out.add(new File());
// 里层目录添加文件
in.add(new File());
in.add(new File());
// 将内层目录放置在外层目录下
out.add(in);
// 修改文件名
out.editName();

控制台输出:

可以看到对最外层目录进行操作后,会递归向下处理当前目录和子目录中所有的文件。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言初阶】函数

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;函数是什么&#xff1f;&#x1f337;函数的分类&#x1f33a;库函数&#x1f33a;自定义函数&#x1f337;函数的参数&#x1f337;函数的调用&#x1f337;函数的嵌套调用和链式访问&#x1f33a;嵌套调用&a…

小游戏也要讲信用

当下&#xff0c;小游戏鱼龙混杂&#xff0c;官方为能更好地保护用户、开发者以及平台的权益&#xff0c;近日宣布7月1日起试行小游戏主体信用分机制。 主体信用分是什么呢&#xff1f;简单来说&#xff0c;这是针对小游戏主体下所有小游戏帐号行为&#xff0c;对开发者进行评…

深度学习中的学习率设置技巧与实现详解

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

(五)Tomcat源码阅读:Engine组件分析

一、概述 在阅读源码之前我们需要对各个类的关系有一个清晰的了解&#xff0c;下面就是Engine各个类之间的关系&#xff0c;我们将会按照从上到下的顺序阅读源码。 二、阅读源码 1、Container &#xff08;1&#xff09;注释 Container可以处理请求并给予相应&#xff0c;并…

JavaScript-扫盲

文章目录1. 前言2. 第一个 JavaScript 程序3. javaScript 的基础语法3.1 变量3.2 数据类型3.3 运算符3.4 条件语句3.5 数组3.6 函数3.7 作用域3.8 对象4. WebAPI4.1 DOM 基本概念4.2 常用 DOM API4.3 事件4.4 操作元素4.5 网页版猜数字游戏4.6 留言版1. 前言 提问 java 和 java…

集合之CurrentHashMap 1.7总结

文章目录底层实现构造方法默认的三个参数什么是Unsafe类&#xff1f;它有什么作用&#xff1f;为什么CurrentHashMap 调用Unsafe方法不会报错&#xff1f;我们自己创建的对象调用会报错&#xff1f;CurrentHashMap的key&#xff0c;value可以为null吗&#xff1f;CurrentHashMa…

水风险指数定义及计算:水资源压力等

水风险指数&#xff08;Water risk indicators&#xff09; 水风险指数&#xff08;Water risk indicators&#xff09;是用来评估水资源可持续性和水相关风险的一种工具&#xff0c;可以通过多种指标来衡量。 1.1 水资源压力&#xff08;water stress, WS&#xff09; 定义…

leetcode -- 142. 环形链表 II

&#x1f428;目录&#x1f4dc;1. 题目&#x1f50d;2. 思路&#x1f511;2.1 链表是否带环&#x1f511;2.2 为何能追上&#x1f511;2.3 入口点的确定&#x1f513;3. 代码实现&#x1f4e1;4. 题目链接&#x1f4dc;1. 题目 给定一个链表的头节点 head&#xff0c;返回链表…

自定义类型 (位段、枚举、联合体)

文章目录&#x1f4ec;位段&#x1f50e;1.什么是位段&#x1f50e;2.位段的内存分配&#x1f50e;3.位段的跨平台问题&#x1f4ec;枚举&#x1f50e;1.枚举类型的定义&#x1f50e;2.枚举的优点&#x1f50e;3.枚举的使用&#x1f4ec;联合&#xff08;共用体&#xff09;&am…

C/C++中for语句循环用法及练习

目录 语法 下面是 for 循环的控制流&#xff1a; 实例 基于范围的for循环(C11) 随堂笔记&#xff01; C语言训练-计算1~N之间所有奇数之和 题目描述 输入格式 输出格式 样例输入 样例输出 环形方阵 干货直达 for 循环允许您编写一个执行特定次数的循环的重复控制结构。…

Go语言基础:数组定义及循环遍历

前言 大家好&#xff0c;我是沐风晓月&#xff0c;本文go语言入门-掌握go语言函数收录于《go语言学习专栏》专栏&#xff0c;此专栏带你从零开始学习go语言&#xff0c;持续更新中&#xff0c;欢迎点赞收藏。 &#x1f3e0;个人主页&#xff1a;我是沐风晓月 &#x1f9d1;个人…

Postman接口与压力测试实例

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。它提供功能强大的 Web API & HTTP 请求调试。 1、环境变量和全局变量设置 环境变量可以使用在以下地方&#xff1a; URLURL paramsHeader valuesform-data/url-encoded valuesRaw body contentHelper fi…

RedgateClone启用并行工作流 crack

RedgateClone启用并行工作流 crack RedgateClone允许您轻松创建用于开发和测试场景的数据库的一次性副本。通过使用生产数据库的克隆来降低成本并提高测试和发布的质量。Redgate克隆支持Microsoft SQL Server、Postgres、Oracle和MySQL数据库。 红门克隆的好处 最多可节省99%的…

CentOS从gcc 4.8.5 升级到gcc 8.3.1

gcc -v查看当前gcc版本。 sudo yum install centos-release-scl-rh安装centos-release-scl-rh。 sudo yum install devtoolset-8-build安装devtoolset-8-build。 显示“Complete!”表示安装成功。 sudo yum install devtoolset-8-gdb安装devtoolset-8-gdb。 显示“Comple…

[JAVA]一步接一步的一起开发-图书管理系统(非常仔细,你一定能看懂)[1W字+]

目录 1.想法 2.框架的搭构 2.1图书 2.1.1Book类 2.1.2BookList类 2.2用户 2.2.1User抽象类 2.2.2AdminUser类&#xff08;管理者&#xff09; 2.2.3NormalUser 2.3操作 操作接口 借阅操作 删除操作 查询操作 归还图书 展示图书 退出系统 2.4小结 3.主函数的编…

【python实操】年轻人,别用记事本保存数据了,试试数据库吧

为什么用数据库&#xff1f; 数据库比记事本强在哪&#xff1f; 答案很明显&#xff0c;你的文件很多时候都只能被一个人打开&#xff0c;不能被重复打开。当有几百万数据的时候&#xff0c;你如何去查询操作数据&#xff0c;速度上要快&#xff0c;看起来要清晰直接 数据库比我…

Azure OpenAI 官方指南03|DALL-E 的图像生成功能与安全过滤机制

2021年1月&#xff0c;OpenAI 推出 DALL-E。这是 GPT 模型在图像生成方面的人工智能应用。其名称来源于著名画家、艺术家萨尔瓦多 • 达利&#xff08;Dal&#xff09;和机器人总动员&#xff08;Wall-E&#xff09;。DALL-E 图像生成器&#xff0c;能够直接根据文本描述生成多…

蓝桥杯真题——模拟灌溉系统

尽量每天都自己写一遍模板&#xff0c;记住模板就好写了 以下内容直接在模板内进行 基本任务&#xff1a;要求“模拟智能灌溉系统”能够实现土壤湿度测量、土壤湿度和时间显示、湿度阈值设 定及存储等基本功能。通过电位器 Rb2 输出电压信号&#xff0c;模拟湿度传感器输出信号…

常见排序算法(C语言实现)

文章目录排序介绍插入排序直接插入排序希尔排序选择排序选择排序堆排序交换排序冒泡排序快速排序递归实现Hoare版本挖坑法前后指针版本非递归实现Hoare版本挖坑法前后指针版本快排的优化三值取中小区间优化归并排序递归实现非递归实现计数排序排序算法复杂度及稳定性分析不同算…

C语言——字符串函数(2)和内存函数

(一)strtok函数dilimiters参数是个字符串&#xff0c;定义了用作分隔符的字符集合第一个参数指定一个字符串&#xff0c;它包含了0个或者多个由dilimiters字符串中一个或者多个分隔符分割的标记。strtok函数找到str中的下一个标记&#xff0c;并将其用 \0 结尾&#xff0c;返回…