设计模式详解(十一)——组合模式

组合模式简介

组合模式定义
组合模式(Composite Pattern)是一种结构型设计模式,又叫部分整体模式,它将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。

组合模式包含以下角色:

  1. Component(抽象构件):抽象构件可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类公有行为的声明和实现,包括添加(add)、删除(remove)、获取子组件(getChildren)以及实现业务逻辑的方法(operation)。它是一个定义了公共的操作方法,可以用于管理和访问component子部件的抽象对象。
  2. Leaf(叶子构件):叶子构件在组合结构中表示叶子节点对象,叶子节点没有子节点,实现了抽象组件接口或抽象类,但没有子组件。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。叶子节点是树形结构中的最底层对象,通常包含具体的业务逻辑实现。
  3. Composite(树枝节点构件):枝节点构件在组合结构中表示容器节点对象,枝节点节点包含子节点,其子节点可以是叶子节点,也可以是其它枝节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义行为,包括那些访问及管理子构件对方法,在其业务方法中可以递归调用其子节点对业务方法。并允许客户端以统一的方式处理其子组件。
  4. Client(客户类):使用组合模式来创建和操作复合对象结构。客户端代码不需要关心对象是叶子节点还是树枝节点,因为所有对象都通过抽象组件接口或抽象类来访问。

组合模式优缺点:
优点:

  1. 客户端代码可以一致地处理单个对象和组合对象,无需关心它们之间的区别。简化了客户端代码;
  2. 组合模式可以优化处理递归或分级数据结构,因为它将对象组织成树形结构,使得对对象的处理更加直观和高效。
  3. 容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

缺点:

  1. 设计复杂性:组合模式可能使设计变得更加复杂,特别是当类之间的层次关系变得复杂时。客户端需要花更多时间来理解这些关系,从而正确地使用组合模式。
  2. 限制容器中的构件:在组合模式中,当需要添加新的容器构件或叶子构件时,可能很难对容器中的构件类型进行限制。这可能导致设计上的混乱和不必要的复杂性。
  3. 继承方法的限制:组合模式通常使用继承来实现,但这可能会限制新的构件只能通过继承来添加新功能。这可能限制了系统的灵活性和可扩展性。
  4. 依赖倒置原则的违反:在某些实现中,组合模式的叶子和树枝的声明可能是实现类而不是接口,这违反了依赖倒置原则。这可能导致代码之间的耦合度过高,不利于维护和扩展。

使用场景

  1. 表示对象的部分和整体层次结构:当需要表示一个对象的部分以及整体层次结构时,组合模式是一个很好的选择。例如,在文件系统中,根目录下有若干文件和目录,在二级目录下还有目录和文件,这种情况下适合使用组合模式。
  2. 忽略组合对象与单个对象的差异:如果客户端需要忽略组合对象与单个对象的差异,以一致的方式处理它们,那么可以使用组合模式。这样,客户端代码可以简化,因为无需关心处理的是单个对象还是组合对象。
  3. 处理递归或分级数据结构:组合模式可以优化处理递归或分级数据结构。通过将对象组织成树形结构,组合模式使得对这些对象的处理更加直观和高效。

通俗来讲就是:
比如在现实生活中,存在很多“部分-整体”的关系。汽车与轮胎、发动机的关系。警察局与科室、警察的关系。学校与学院、学生、老师的关系。
组合模式是一种非常普遍和常用的模式,接口服务互相组合,提供更丰富的接口,实现复杂的业务逻辑。一般情况会选择使用组合代替继承,组合更灵活、更方便。

以下举一个组合模式的例子:
假设学校中有校长管理老师,老师学生,通过以下实例演示学校中人员的层次结构:

创建抽象类,组件Persion 【Component(组件)】

import java.util.List;/*** Component(组件)** 为组合中的对象声明接口* 声明一个接口用于访问和管理Component的子组件*/public abstract class Persion {private String name;protected List<Persion> persionList;public abstract void add(Persion persion);public abstract void delete(Persion persion);public void input() {System.out.println(String.format("name is %s", name));};public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Persion> getPersionList() {return persionList;}
}

创建具体类Principal【Composite(树枝节点构件)】

import java.util.ArrayList;/*** Composite(树枝节点构件)** 实现了在抽象构件中定义行为,包括那些访问及管理子构件对方法* 存储子部件**/
public class Principal extends Persion {public Principal(String name) {setName(name);persionList = new ArrayList<Persion>();}@Overridepublic void add(Persion persion) {persionList.add(persion);}@Overridepublic void delete(Persion persion) {persionList.remove(persion);}
}

创建具体类Teacher【Composite(树枝节点构件)】

import java.util.ArrayList;/*** Composite(树枝节点构件)** 实现了在抽象构件中定义行为,包括那些访问及管理子构件对方法* 存储子部件**/
public class Teacher extends Persion {public Teacher(String name) {setName(name);persionList = new ArrayList<Persion>();}@Overridepublic void add(Persion persion) {persionList.add(persion);}@Overridepublic void delete(Persion persion) {persionList.remove(persion);}
}

创建具体类Student【Leaf(叶子构件)】

/*** Leaf(叶子构件)** 叶子构件在组合结构中表示叶子节点对象,叶子节点没有子节点* 对于那些访问及管理子构件的方法,可以通过异常等方式进行处理*/
public class Student extends Persion{public Student(String name) {setName(name);persionList = null;}@Overridepublic void add(Persion persion) {}@Overridepublic void delete(Persion persion) {}
}

创建测试类【Client(客户类)】

/*** Client(客户类)* 使用组合模式来创建和操作复合对象结构*
*/
public class Client {public static void main(String[] args) {Persion principal = new Principal("校长");Persion teacher1 = new Teacher("教师1");Persion teacher2 = new Teacher("教师2");Persion student1 = new Student("学生1");Persion student2 = new Student("学生2");Persion student3 = new Student("学生3");Persion student4 = new Student("学生4");principal.add(teacher1);principal.add(teacher2);teacher1.add(student1);teacher1.add(student2);teacher2.add(student3);teacher2.add(student4);info("无需", principal);}public static void info(String pre ,Persion persion){System.out.println(String.format("%s管理:%s", pre, persion.getName()));if(null == persion.getPersionList()){return;}for(Persion persion1 : persion.getPersionList()){info(persion.getName(), persion1);}}}

输出结果如下所示:

无需管理:校长
校长管理:教师1
教师1管理:学生1
教师1管理:学生2
校长管理:教师2
教师2管理:学生3
教师2管理:学生4

从结果可以看成功根据需求,获取到了校长管理老师,老师管理学生的层级结构。

总而言之:
组合模式,它是一种非常强大的结构型设计模式,用于创建复杂的对象结构,允许用户以统一的方式处理单个对象和复合对象。通过组合模式,你可以构建出具有层次结构的对象模型,这些对象可以像单个对象一样被简单、一致地使用。
组合模式提供一个结构,可同时包容个别对象和组合对象;允许客户对个别对象以及组合对象一视同仁;组合结构内的任意对象称为组件;组件可以是组合,也可以是叶节点;在使用组合模式时,要多加考虑方式,有的时候可以与迭代器模式配合使用。


以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git

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

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

相关文章

AWS安全组是什么?有什么用?

最近看到小伙伴在问&#xff0c;AWS安全组是什么&#xff1f;有什么用&#xff1f;今天我们大家就来简单聊聊&#xff0c;仅供参考哦&#xff01; AWS安全组是什么&#xff1f;有什么用&#xff1f; 【回答】&#xff1a;AWS安全组是一种虚拟防火墙&#xff0c;用于控制进出…

保存Json对象到数据库

文章目录 背景实现方式1. 直接以 Json 对象保存到数据库2. 以 String 类型保存到数据库 背景 项目过程中可能需要保存 Json 对象到数据库中。 实现方式 有两种实现方式&#xff0c;一种是直接保存 Json 对象到数据库&#xff0c;这种方式在创建实体类以及编写 Mapper XML 脚本…

【畅玩雾锁王国】雾锁王国服务器手动部署教程2024年

阿里云雾锁王国服务器搭建教程是基于计算巢服务&#xff0c;3分钟即可成功创建Enshrouded游戏服务器&#xff0c;阿里云8核32G雾锁王国专用游戏服务器90元1个月、271元3个月&#xff0c;阿里云服务器网aliyunfuwuqi.com亲自整理雾锁王国服务器详细搭建教程&#xff1a; 一、前…

游戏配置二级缓存一致性问题解决方案

游戏服务器进程在启动的时候&#xff0c;一般会把所有策划配置数据加载到内存里&#xff0c;将主键以及对应的记录存放在一个HashMap容器里&#xff0c;这称为一级缓存。部分功能可能还需要缓存其他数据&#xff0c;这些称为二级缓存。举个例子&#xff0c;对于如下的玩家升级表…

Elasticsearch:了解人工智能搜索算法

作者&#xff1a;来自 Elastic Jessica Taylor, Aditya Tripathi 人工智能工具无处不在&#xff0c;其原因并不神秘。 他们可以执行各种各样的任务并找到许多日常问题的解决方案。 但这些应用程序的好坏取决于它们的人工智能搜索算法。 简单来说&#xff0c;人工智能搜索算法是…

采用uniapp实现的银行卡卡片, 支持H5和微信小程序

采用uniapp-vue3实现的银行卡卡片 支持H5、微信小程序&#xff08;其他小程序未测试过&#xff0c;可自行尝试&#xff09; 可用于参考学习 可到插件市场下载尝试&#xff1a; https://ext.dcloud.net.cn/plugin?id16736 使用示例

《Python 语音转换简易速速上手小册》第2章 Python 编程基础(2024 最新版)

文章目录 2.1 Python 语言基础2.1.1 基础知识深入基础总结 2.1.2 主要案例&#xff1a;数据分析脚本案例介绍案例 Demo案例分析 2.1.3 扩展案例 1&#xff1a;自动化邮件发送案例介绍案例 Demo案例分析 2.1.4 扩展案例 2&#xff1a;网页数据抓取案例介绍案例 Demo案例分析 2.2…

将本地项目上传到svn服务端和git

一、SVN 1.创建svn库,下面生成了三个文件夹,branches指分支,trunk下可以放项目 2.在本地checkout,填入svn库的地址,因为是新建的,所以checkout的是空文件夹 把自己的项目复制到trunk下,在项目上 右键-TortoiseSVN-add add完之后 右键-svn commit 3.idea打开这个项目,将项目跟…

C++面试宝典第31题:有效的数独

题目 判断一个9 x 9的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。 1、数字1-9在每一行只能出现一次。 2、数字1-9在每一列只能出现一次。 3、数字1-9在每一个以粗实线分隔的3 x 3宫内只能出现一次。 下图是一个部分填充的有效的数独,数独部分空格内已…

爬虫在网页抓取的过程中可能会遇到哪些问题?

在网页抓取&#xff08;爬虫&#xff09;过程中&#xff0c;开发者可能会遇到多种问题&#xff0c;以下是一些常见问题及其解决方案&#xff1a; 1. IP封锁&#xff1a; 问题&#xff1a;封IP是最常见的问题&#xff0c;抓取的目标网站会识别并封锁频繁请求的IP地址。 解决方案…

Js如何判断两个数组是否相等?

本文目录 1、通过数组自带方法比较2、通过循环判断3、toString()4、join()5、JSON.stringify() 日常开发&#xff0c;时不时会遇到需要判定2个数组是否相等的情况&#xff0c;需要实现考虑的场景有&#xff1a; 先判断长度&#xff0c;长度不等必然不等元素位置其他情况考虑 1…

Spring Boot中的@Scheduled注解:定时任务的原理与实现

1. 前言 本文将详细探讨Spring Boot中Scheduled注解的使用&#xff0c;包括其原理、实现流程、步骤和代码示例。通过本文&#xff0c;读者将能够了解如何在Spring Boot应用中轻松创建和管理定时任务。 2. Scheduled注解简介 在Spring框架中&#xff0c;Scheduled注解用于标记…

《Python 语音转换简易速速上手小册》第5章 音频数据处理(2024 最新版)

文章目录 5.1 音频数据的基本处理5.1.1 基础知识5.1.2 主要案例&#xff1a;音频剪辑工具案例介绍案例 Demo案例分析 5.1.3 扩展案例 1&#xff1a;自动音量调节器案例介绍案例 Demo案例分析 5.1.4 扩展案例 2&#xff1a;语音识别预处理案例介绍案例 Demo案例分析 5.2 使用 Py…

手把手教您安装2024最新版微信消息防撤回插件

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f3e1; 环境 &#x1f3e1;&#x1f4d2; 使用方法 &#x1f4d2;&#x1f4dd; 步骤一&#x1f4dd; 步骤二 ⚓️ 相关链接 ⚓️ &#x1f4d6; 介绍 &#x1f4d6; 本文与大家分享一个大神开发的2024最新版本的微信消息防撤…

解决vite打包出现 “default“ is not exported by “node_modules/...问题

项目场景&#xff1a; vue3tsvite项目打包 问题描述 // codemirror 编辑器的相关资源 import Codemirror from codemirror;error during build: RollupError: "default" is not exported by "node_modules/vue/dist/vue.runtime.esm-bundler.js", impor…

修改Springboot默认序列化工具Jackson的配置

如果我们在Spring Boot应用中手动定义并注入了一个ObjectMapper Bean&#xff0c;那么这个自定义的ObjectMapper实例会替换掉Spring Boot默认配置的ObjectMapper。当Spring容器中存在多个同类型的Bean时&#xff0c;默认情况下最后一个创建的Bean将作为首选Bean&#xff08;如果…

Tomcat 学习之 Servlet

目录 1 Servlet 介绍 2 创建一个 Servlet 3 web.xml 介绍&#xff08;不涉及 filter 和 listener 标签&#xff09; 3.1 display-name 3.2 welcome-file-list 3.3 servlet 3.4 session-config 3.5 error-page 4 Tomcat 如何根据 URL 定位到 Servlet 5 执行 Servlet …

debezium源码之启动快照7步曲

欢迎收藏关注点赞&#xff0c; 持续输出CDC、debezium、flinkcdc内容&#xff0c;比心 代码仓库地址&#xff1a;https://github.com/debezium/debezium/blob/main/debezium-core/src/main/java/io/debezium/relational/RelationalSnapshotChangeEventSource.java 代码版本de…

不破不立,那些年错过的Python

随着OpenAI的发展&#xff0c;Python的重要性不言而喻。不知你是否和我一样&#xff0c;不知道曾经说过多少次我要学Python&#xff0c;都没有执行起来… 近期我在知识库中更新了一波Python教程&#xff0c;选取了这一篇分享给大家。 前言 很多时候我们需要让程序变成交互性的…

Linux系统——nginx服务介绍

一、Nginx——高性能的Web服务端 Nginx的高并发性能优于httpd服务 1.nginx概述 Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的&#xff0c;开发工作最早从2002年开始&#xff0c;第一次公开发布时间是2004年10月4日&#xff0c;版本…