【设计模式深度剖析】【4】【结构型】【组合模式】| 以文件系统为例加深理解

news2024/11/17 15:29:59

👈️上一篇:适配器模式

设计模式深度剖析-专栏👈️

目 录

  • 组合模式
  • 定义
    • 英文原话
    • 直译
    • 如何理解?
  • 3个角色
    • UML类图
    • 代码示例
  • 组合模式的优点
  • 组合模式的使用场景
  • 示例解析:文件系统

组合模式

组合模式(Composite Pattern)也叫合成模式,用来描述部分与整体的关系。

  • 高层模块调用简单。一棵树形结构中的所有节点都是 Component,局部和整体对调用者来说没有任何区别,即高层模块不必关心自己处理的是单个对象还是整个组合结构**,**简化了高层模块的代码。
  • 节点自由增加。使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可。

当我们发现需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

定义

英文原话

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

直译

将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端能够统一地处理单个对象和对象的组合。

如何理解?

叶子构件和容器构件实现了抽象构件,即实现了相同的接口,用户对单个对象和组合对象的使用具有一致性。

3个角色

UML类图

CompositePattern.png

组合模式(Composite Pattern)允许我们将对象组合成树形结构以表示“部分整体”的层次结构,使得客户端以统一的方式处理单个对象和对象的组合。以下是组合模式中的主要角色:

  1. 抽象构件(Component):它可以是接口或抽象类,为叶子和容器对象声明接口,在该接口中包含用于管理子对象的方法以及用于自身操作的方法。在组合模式中,抽象构件定义了叶子和容器构件的共同行为。
  2. 叶子构件(Leaf):叶子对象继承自抽象构件,它没有子节点,通常用于实现抽象构件中的业务方法。在组合结构中,叶子节点没有子节点,其实现了在抽象构件中定义的行为。
  3. 容器构件(Composite):容器对象也继承自抽象构件,并包含一组子构件。它实现了在抽象构件中定义的行为,并提供了添加、删除和访问其子对象的方法。容器构件可以包含其他容器或叶子,从而实现复杂的树形结构。
  4. 客户端(Client):通过抽象构件接口与组合结构进行交互。对于客户端而言,叶子对象和容器对象是一致的,客户端不需要区分它们。

代码示例

以下是一个简单的Java示例来说明组合模式:

// 抽象构件  
public interface Component {
    void operation();
}
// 叶子构件  
public class Leaf implements Component{
    @Override
    public void operation() {
        // 业务处理逻辑
        System.out.println("leaf...");
    }
}
// 容器构件  
public class Composite implements Component {
    // 构件容器
    private ArrayList<Component> componentList = new ArrayList<>();

    // 添加构件
    public void add(Component component) {
        this.componentList.add(component);
    }

    // 删除构件
    public void remove(Component component) {
        this.componentList.remove(component);
    }

    // 获取子构件
    public ArrayList<Component> getChild() {
        return this.componentList;
    }

    @Override
    public void operation() {
        // 业务逻辑
        System.out.println("branch...");
    }
}
// 客户端代码  
public class DemoTest {
    public static void main(String[] args) {
        // 创建一个根节点
        Composite root = new Composite();
        root.operation();
        // 创建树枝节点
        Composite branch = new Composite();
        // 创建叶子节点
        Leaf leaf = new Leaf();
        // 构建树形结构
        root.add(branch);
        branch.add(leaf);
        display(root);
    }

    // 遍历树(递归)
    public static void display(Composite root) {
        for (Component c : root.getChild()) {
            if(c instanceof Leaf){// 如果节点类型是叶子节点
                c.operation();
            }else{// 树枝节点
                c.operation();
                display((Composite) c);
            }
        }
    }
}
/* Output:
branch...
branch...
leaf...
*///~

在这个例子中,我们有一个Component接口,它定义了一个名为operation的方法。Leaf类实现了这个接口,并提供了具体的实现。Composite类同样实现了Component接口,并维护了一个子组件的列表。

组合模式的优点

  1. 高层模块调用简单。一棵树形机构中的所有节点都是 Component,局部和整体对调用者来说没有任何区别即高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码
  2. 节点自由增加。使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可。

组合模式的使用场景

使用组合模式的典型场景如下。

  1. 需要描述对象的部分和整体的等级结构,如树形菜单、文件和文件夹管理
  2. 需要客户端忽略个体构件和组合构件的区别,平等对待所有的构件

示例解析:文件系统

FileSystemDemo.png

在生活中,一个常见的组合模式的例子是文件系统。文件系统中的文件和文件夹可以看作是组合模式的实现,其中文件夹可以包含文件和其他文件夹(子文件夹),而文件则不包含任何子项。

以下是使用Java实现的示例,模拟了一个简单的文件系统:

// 抽象构件:文件或文件夹  
public interface FileSystemElement {  
    void display();  
}  
// 叶子构件:文件  
public class File implements FileSystemElement {  
    private String name;  
  
    public File(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public void display() {  
        System.out.println("File: " + name);  
    }  
}  
// 容器构件:文件夹  
public class Folder implements FileSystemElement {  
    private String name;  
    private List<FileSystemElement> children = new ArrayList<>();  
  
    public Folder(String name) {  
        this.name = name;  
    }  
  
    public void add(FileSystemElement element) {  
        children.add(element);  
    }  
  
    public void remove(FileSystemElement element) {  
        children.remove(element);  
    }  
  
    @Override  
    public void display() {  
        System.out.println("Folder: " + name);  
        for (FileSystemElement child : children) {  
            child.display();  
        }  
    }  
}  
// 客户端代码
public class DemoTest {
    public static void main(String[] args) {
        // 创建文件夹和文件  
        Folder rootFolder = new Folder("root");
        Folder documentsFolder = new Folder("Documents");
        Folder picturesFolder = new Folder("Pictures");
        File file1 = new File("example.txt");
        File file2 = new File("image.jpg");

        // 将文件和文件夹添加到对应的父文件夹中  
        rootFolder.add(documentsFolder);
        rootFolder.add(picturesFolder);
        documentsFolder.add(file1);
        picturesFolder.add(file2);

        // 显示整个文件系统的结构  
        rootFolder.display();
    }
}

/* Output:
Folder: root
Folder: Documents
File: example.txt
Folder: Pictures
File: image.jpg
*///~

在这个示例中,FileSystemElement是抽象构件接口,它声明了一个display方法用于显示文件或文件夹的信息。File类实现了这个接口,表示一个具体的文件。Folder类也实现了这个接口,表示一个文件夹,并且它有一个children列表来存储其子元素(文件和文件夹)。Folder类还提供了添加和删除子元素的方法。

DemoTest类的main方法中,我们创建了一个根文件夹rootFolder,并添加了documentsFolderpicturesFolder两个子文件夹。接着,我们向这两个文件夹中分别添加了一个文件和图片。最后,我们调用rootFolderdisplay方法来显示整个文件系统的结构。

这个输出展示了组合模式中的层次结构,其中文件夹可以包含文件和子文件夹,而文件则不包含任何子项。

👈️上一篇:适配器模式

设计模式深度剖析-专栏👈️

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

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

相关文章

【经典论文阅读10】MNS采样——召回双塔模型的最佳拍档

这篇发表于2020 WWW 上的会议论文&#xff0c;提出一种MNS方式的负样本采样方法。众所周知&#xff0c;MF方法难以解决冷启动问题&#xff0c;于是进化出双塔模型&#xff0c;但是以双塔模型为基础的召回模型的好坏十分依赖负样本的选取。为了解决Batch内负样本带来的选择性偏差…

IT廉连看——UniApp——条件渲染

IT廉连看——UniApp——条件渲染 什么是条件渲染&#xff1f; 顾名思义&#xff0c;满足一定的条件他才会进行渲染。 这是我们上节事件绑定保留的代码。 一、现在我有这样一个需求&#xff1a; 增加一个按钮&#xff0c;当我点击这个按钮&#xff0c;这里的文本&#xff0…

ICML 2024 | 即插即用!无需训练!基于球面高斯约束引导的条件扩散模型

©PaperWeekly 原创 作者 | 杨凌霄 单位 | 上海科技大学信息学院 论文标题&#xff1a; Guidance with Spherical Gaussian Constraint for Conditional Diffusion 论文作者&#xff1a; 杨凌霄、丁枢桐、蔡逸凡、虞晶怡、汪婧雅、石野 通讯作者&#xff1a; 石野 论文链接…

【数据结构】二叉树-堆(上)

个人主页~ 二叉树-堆 一、树的概念及结构1、概念2、相关概念3、树的表示4、树的实际应用 二、二叉树的概念和结构1、概念2、特殊二叉树3、二叉树的性质4、二叉树的存储结构&#xff08;1&#xff09;顺序存储&#xff08;2&#xff09;链式存储 三、二叉树的顺序结构以及实现1、…

【Linux-时间管理和内核定时器】

Linux-时间管理和内核定时器 ■ 设置系统节拍率■ 高节拍率和低节拍率的优缺点&#xff1a;■ jiffies 系统节拍数■ get_jiffies_64 这个函数可以获取 jiffies_64 的值■ 处理绕回■ 使用 jiffies 判断超时 ■ jiffies 和 ms、 us、 ns 之间的转换函数在这里插入代码片■ 内核…

pytest:指定测试用例执行顺序

在自动化测试中&#xff0c;测试用例的执行顺序有时对测试结果具有重要影响。本文将介绍如何在pytest框架中使用pytest-ordering插件以及Collection hooks来控制测试用例的执行顺序。 方式1&#xff1a; 使用pytest-ordering插件控制执行顺序 1.1 安装pytest-ordering插件 首…

Android Studio开发之路(十三)主题影响Button颜色问题解决及button自定义样式

一、问题描述 在开发过程中发现安卓的默认主题色是紫色&#xff0c;并且会导致button也是紫色&#xff0c;有时直接在xml布局文件中直接设置button的背景色或者设置背景图片不起效果 方案一、如果是app&#xff0c;可以直接设置主题颜色 比如&#xff0c;将主题设置为白色&a…

【STM32】 独立看门狗配置方法

什么是看门狗 看门狗&#xff08;watchdog&#xff09;指的是一种监控系统或程序&#xff0c;用于定期检测和监控其他系统或程序的运行状态&#xff0c;并在出现问题或故障时采取相应的措施。它可以是硬件设备&#xff0c;也可以是软件程序。 在计算机领域中&#xff0c;看门狗…

Java Swing + MySQL图书借阅管理系统

系列文章目录 Java Swing MySQL 图书管理系统 Java Swing MySQL 图书借阅管理系统 文章目录 系列文章目录前言一、项目展示二、部分代码1.Book2.BookDao3.DBUtil4.BookAddInternalFrame5.Login 三、配置 前言 项目是使用Java swing开发&#xff0c;界面设计比较简洁、适合作…

Taipy快速打造数据驱动的Web应用

Taipy&#xff1a; 用Taipy&#xff0c;让数据洞察与应用开发无缝对接- 精选真开源&#xff0c;释放新价值。 概览 Taipy快速打造数据驱动的 Web 应用。这是一个基于 Python 和 Flask 的项目&#xff0c;结合了 React 等前端技术&#xff0c;为开发者提供了一个简洁、高效的开…

【计算机毕业设计】基于SSM+Vue的新能源汽车在线租赁管理系统【源码+lw+部署文档】

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;新能源汽车在线租赁当然也不能排除在外。新能源汽车在线租赁是以实际运用为开发背景&#xff0c;运用软件工程开发方法&…

docker安装Elasticsearch(ES)详细教程

使用Docker来安装Elasticsearch&#xff08;简称ES&#xff09;的详细教程如下&#xff1a; 1. 前提条件 确保你的系统已经安装了Docker&#xff0c;并且Docker服务正在运行。如果你使用的是Windows系统&#xff0c;还需要确保已经启用了Hyper-V和容器功能。 2. 拉取Elastic…

AOP、注解、EL表达、若依权限,Security原理综合分析

AOP、注解、EL表达、若依权限&#xff0c;Security原理综合分析 案例一&#xff1a;更新、创建增强 需求产生 每个表中均有创建时间、创建人、修改时间、修改人等字段。 在操作时候手动赋值&#xff0c;就会导致编码相对冗余、繁琐&#xff0c;那能不能对于这些公共字段在某…

【c++基础】和谐分组

题目描述 s 班共有 n 名学生&#xff0c;按照学号从 1 到的顺序每名学生的身高分别为 a[1],a[2]...a[n]。由于是新学期&#xff0c;s 班需要进行分组&#xff0c;分组的要求如下&#xff1a; 进行分组的组数不能超过 k。 每组的人的学号必须相邻。 由于身高差过大的人分在同一…

今天又一次在金边搬家了

target&#xff1a;离开柬埔寨倒计时-220day 前言 前天&#xff0c;银行的行政告诉我之前住的地方那个中介说房东不租了&#xff0c;重新给我租了个地方&#xff0c;还是在同一栋楼&#xff0c;只是楼层和房间不一样&#xff0c;今天搬了好多躺呀… 周末的日子 昨天下午 同事&…

2024 在Pycharm管理数据库

2024 在Pycharm管理数据库 Pycharm 社区版DataBase Navigator 数据库管理插件(Plugins)安装使用(sqlite为例添加数据) 文章目录 2024 在Pycharm管理数据库一、Pycharm数据库配置1、Database Navigator插件安装2、连接数据库 二、数据库使用1、插件自带基本操作2、控制台操作 …

linux centos循环ping网段ip

循环ping&#xff0c;检测ip是否可用&#xff0c;ping通为正在使用yes&#xff0c;no为不通 vim test.sh#!/bin/bash ip"192.168.1."echo "ping log:" > ./ping.txt for i in {1..128} doping -c 1 -w 1 -W 1 $ip$i | grep -q "ttl" &&a…

Redis崩溃后,如何进行数据恢复的?no.24

本课时我们主要学习通过 RDB、AOF、混合存储等数据持久化方案来解决如何进行数据恢复的问题。 Redis 持久化是一个将内存数据转储到磁盘的过程。Redis 目前支持 RDB、AOF&#xff0c;以及混合存储三种模式。 RDB Redis 的 RDB 持久化是以快照的方式将内存数据存储到磁盘。在…

【数据结构与算法 经典例题】相交链表

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;数据结构与算法刷题系列&#xff08;C语言&#xff09; 期待您的关注 目录 一、问题描述 二、解题思路 方法一:双循环对比法 方…

Minecraft服务器如何搭建

Minecraft这是原版英文名称&#xff0c;在中国大陆被译为《我的世界》&#xff0c;这款游戏很火爆。台湾的很多小伙伴也在玩&#xff0c;其译名为《我的创世神》。现在这款游戏在国内已经被网易代理了。因为这款游戏开源&#xff0c;所以任何人都可以搭建服务器端&#xff0c;如…