16结构型模式-组合模式

news2024/9/22 1:27:45

我们很容易将“组合模式”和“组合关系”搞混。组合模式最初只是用于解决树形结构的场景,更多的是处理对象组织结构之间的问题。而组合关系则是通过将不同对象封装起来完成一个统一功能.

1 组合模式介绍

将对象组合成树形结构以表示整个部分的层次结构.组合模式可以让用户统一对待单个对象和对象的组合.
在这里插入图片描述
在这里插入图片描述

2 组合模式原理

在这里插入图片描述
在这里插入图片描述

3 组合模式实现

组合模式的关键在于定义一个抽象根节点类,它既可以代表叶子,又可以代表树枝节点,客户端就是针对该抽象类进行编程,不需要知道它到底表示的是叶子还是容器,可以对其进行统一处理.

树枝节点对象和抽象根节点类之间建立了一个聚合关联关系,在树枝节点对象中既可以包含叶子节点,还可以继续包含树枝节点,以此实现递归组合,形成一个树形结构.

/**
 * 抽象根节点角色
 * 对客户端而言,只需要针对抽象编程,无需关心具体子类是树枝节点还是叶子节点
 **/
public abstract class Component {

    public abstract  void add(Component c); //增加节点
    public abstract void remove(Component c); //删除节点
    public abstract Component getChild(int i); //获取节点
    public abstract void operation(); //业务方法
}
/**
 * 叶子节点
 * 叶子节点中不能包含子节点
 **/
public class Leaf extends Component {
    @Override
    public void add(Component c) {
    }

    @Override
    public void remove(Component c) {
    }

    @Override
    public Component getChild(int i) {
        return null;
    }

    @Override
    public void operation() {
        //叶子节点中的具体方法
    }
}
/**
 * 树枝节点
 * 树枝节点类是一个容器对象,它既可以包含树枝节点也可以包含叶子节点
 **/
public class Composite extends Component {

    //定义集合属性,保存子节点的数据
    private ArrayList<Component> list = new ArrayList<>();

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public Component getChild(int i) {
        return list.get(i);
    }

    //具体业务方法
    @Override
    public void operation() {
        //在循环中,递归调用其他节点中的operation() 方法
        for (Component component : list) {
            component.operation();
        }
    }
}
4 组合模式应用实例

在这里插入图片描述
我们按照下图的表示,进行文件和文件夹的构建.
在这里插入图片描述
Entry类: 抽象类,用来定义File类和Directory类的共性内容

/**
 * Entry抽象类 (文件夹+文件)
 **/
public abstract class Entry {

    public abstract String getName(); //获取文件名

    public abstract int getSize(); //获取文件大小

    //添加文件或者文件夹方法
    public abstract Entry add(Entry entry);

    //显示指定目录下的所有文件的信息
    public abstract void printList(String prefix);

    @Override
    public String toString() {
        return getName() +"(" + getSize() +")";
    }
}

File类,叶子节点,表示文件.

/**
 * File类,表示文件
 **/
public class File extends Entry{

    private String name; //文件名
    private int size; //文件大小

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

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public int getSize() {
        return this.size;
    }

    @Override
    public Entry add(Entry entry) {
        return null;
    }

    @Override
    public void printList(String prefix) {

        System.out.println(prefix + "/" + this);
    }
}

Directory类,树枝节点,表示文件


/**
 * Directory 容器对象,表示文件夹
 **/
public class Directory extends Entry {

    //文件的名字
    private String name;

    //文件夹和文件的集合
    private ArrayList<Entry> directory = new ArrayList<>();

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

    @Override
    public String getName() {
        return this.name;
    }


    /**
     * 获取文件大小
     *      1.如果entry对象是file类型,则调用getSize方法获取文件大小
     *      2.如果entry对象是Directory类型,会继续调用子文件夹的getSize()方法,形成递归调用
     */
    @Override
    public int getSize() {

        int size = 0;

        //遍历获取文件大小
        for (Entry entry : directory) {
            size += entry.getSize();
        }

        return size;
    }

    @Override
    public Entry add(Entry entry) {
        directory.add(entry);
        return this;
    }

    @Override
    public void printList(String prefix) {
        System.out.println("/" + this);
        for (Entry entry : directory) {
            entry.printList("/" + name);
        }
    }
}

测试

public class Client {

    public static void main(String[] args) {

        //创建根节点
        Directory rootDir = new Directory("root");

        //创建树枝节点
        Directory binDir = new Directory("bin");
        //向bin目录添加叶子节点
        binDir.add(new File("vi",10000));
        binDir.add(new File("test",20000));

        Directory tmpDir = new Directory("tmp");

        Directory usrDir = new Directory("usr");
        Directory mysqlDir = new Directory("mysql");
        mysqlDir.add(new File("my.cnf",30));
        mysqlDir.add(new File("test.db",25000));
        usrDir.add(mysqlDir);

        //将所有子文件夹封装到根节点
        rootDir.add(binDir);
        rootDir.add(tmpDir);
        rootDir.add(usrDir);

        rootDir.printList("");
    }
}
5 组合模式总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

红日靶场复现1

红日靶场复现1&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f388;&#x1f388;&#x1f389;&#x1f388;&#x1f388;&#x1f389; 一、主机发现&#x1f388;&#x1…

CV计算机视觉每日开源代码Paper with code速览-2023.10.23

精华置顶 墙裂推荐&#xff01;小白如何1个月系统学习CV核心知识&#xff1a;链接 点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【目标检测】Zone Evaluation: Revealing Spatial Bias i…

【C语言】【goto语句】复习捡拾~

goto语句可以在同一个函数内跳转到设定好的位置&#xff1a; #include<stdio.h> int main() {printf("hello world\n");goto next;printf("hehe"); next:printf("leap here\n");return 0; }goto 语句如果使⽤的不当&#xff0c;就会导致在…

Quantinuum联合中部大学量子物理学家突破“量子+AI”研究

近期&#xff0c;集成量子计算公司Quantinuum和日本中部大学宣布建立新合作&#xff0c;由AI量子模型领域的两位全球专家Bob Coecke和小泽正直&#xff08;Masanao Ozawa&#xff09;教授共同领导。作为各自领域公认的技术领导者&#xff0c;他们将建立一个跨学科团队来探索量子…

判断是否为Base64加密无意间发现特殊字符无法判断

一&#xff1a;思路 判断一个字符串是否为base64编码的流程&#xff1a; 步骤 描述 1 将字符串转换为字节数组 2 判断字节数组的长度是否是4的倍数 3 将字节数组的每个字节转换为对应的base64字符 4 判断base64字符是否合法 二&#xff1a;代码 /*** 判断是否…

《算法通关村——双指针妙用》

《算法通关村——双指针妙用》 删除元素 描述 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。要求&#xff1a;不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组…

代碼隨想錄算法訓練營|第四十五天|1049. 最后一块石头的重量 II、494. 目标和、474.一和零。刷题心得(c++)

目录 讀題 1049. 最后一块石头的重量 II 自己看到题目的第一想法 看完代码随想录之后的想法 494. 目标和 自己看到题目的第一想法 看完代码随想录之后的想法 474.一和零 自己看到题目的第一想法 看完代码随想录之后的想法 1049. 最后一块石头的重量 II - 實作 思路 …

Redis -- 基础知识2

1.Redis客户端介绍 1.基础介绍 Redis是一种客户端-服务器结构的程序&#xff0c;通过网络进行互动 客户端的多种形态 1.自带了命令行客户端&#xff1a;redis-cil 2.图形化界面的客户端&#xff1a;依赖windows系统&#xff0c;连接服务器有诸多限制&#xff0c;不建议使用 3.基…

简单而高效:使用PHP爬虫从网易音乐获取音频的方法

概述 网易音乐是一个流行的在线音乐平台&#xff0c;提供了海量的音乐资源和服务。如果你想从网易音乐下载音频文件&#xff0c;你可能会遇到一些困难&#xff0c;因为网易音乐对其音频资源进行了加密和防盗链的处理。本文将介绍一种使用PHP爬虫从网易音乐获取音频的方法&…

Fastq文件的获取

Fastq文件的获取 Fastq文件的获取linux 下安装SRA Toolkit工具使用SRA Toolkit工具下载SRA数据 Fastq文件的获取 author:CYH-BI date:2023.10.25 Fastq文件得获取 ,可以从NCBI获取&#xff0c;也可以自己测序得到结果&#xff0c;下面介绍从网上获取数据。 linux 下安装SRA…

MySQL3:MySQL中一条更新SQL是如何执行的?

MySQL3&#xff1a;MySQL中一条更新SQL是如何执行的&#xff1f; MySQL中一条更新SQL是如何执行的&#xff1f;1.Buffer Pool缓冲池2.Redo logredo log作用Redo log文件位置redo log为什么是2个&#xff1f; 3.Undo log4.更新过程5.InnoDB官网架构InnoDB架构-内存结构①Buffer …

【uniapp+云函数调用】人脸识别,实人认证,适用于app,具体思路解析,已实现

2023.10.8 需求: uniapp开发的app项目中使用人脸识别 app项目都是第一次搞,更别提人脸识别了。目前已有的就是Dcloud账号已申请,实现需求的时间没那么紧迫 此篇会详细记录从0到1的过程 2023.10.24 今天开始探究实现的过程 可能会记录的有些冗余 效果图如下: uniapp开发指南…

GoLong的学习之路(九)语法之结构体(非常重要,不看就等于不会Go语言)

书接上回&#xff0c;上回书说到&#xff0c;map等数据结构&#xff0c;接下来说结构体 文章目录 类型别名和自定义类型自定义类型别名类型定义和类型别名的区别 结构体结构体的定义结构体实例化基本实例化 匿名结构体创建指针类型结构体并取用获取结构体指针取用结构体 结构体…

NewStarCTF2023week4-More Fast(GC回收)

打开链接&#xff0c;存在很多个类&#xff0c;很明显是php反序列化漏洞利用&#xff0c;需要构造pop链 &#xff0c; 关于pop链构造的详细步骤教学&#xff0c;请参考我之前的博客&#xff0c;真的讲得很详细也容易理解&#xff1a; http://t.csdnimg.cn/wMYNB 如果你是刚接…

降本增效神器?Share Creators 智能数字资产管理系统真香!

降本增效似乎是一个持续又永久的话题。尤其在今年&#xff0c; 显得格外的重要~ 在各行各业都受到了疫情所带来巨大冲击的背景下&#xff0c;降本增效对很多企业来说不再是锦上添花&#xff0c;而可能是一条唯一的出路。 随着市场的收缩和竞争的加剧&#xff0c;在更“卷”的…

树形数据增删改查

功能描述&#xff1a; 默认展示所有项目点击项目展示当前项目下的所有区域点击区域展示当前区域下的所有工位以上以树形图格式展示项目&#xff0c;区域&#xff0c;和工位都可进行增加 修改 和删除&#xff0c;每个图标hover时显示对应提示信息项目&#xff0c;区域&#xff…

数据库数据恢复—Oracle数据库报错ORA-01110错误的数据恢复案例

Oracle数据库故障&#xff1a; 北京某公司一台运行oracle数据库的服务器&#xff0c;机房意外断电导致该服务器重启&#xff0c;重启后发现oracle数据库报错。该Oracle数据库没有备份。 Oracle数据库数据恢复过程&#xff1a; 1、北亚企安数据恢复工程师检查该oracle数据库的数…

外卖跑腿小程序开发是否需要定期更新和维护?

外卖跑腿小程序已成为现代生活的一部分&#xff0c;但它们的成功和可靠性取决于持续的定期更新和维护。本文将探讨为什么外卖跑腿小程序需要定期更新和维护&#xff0c;以及如何实施这些关键的技术措施。 为什么需要定期更新和维护&#xff1f; 1. 改进性能和稳定性 外卖跑…

Android Studio模拟器/虚拟设备连接互联网的方法

如图&#xff0c;无线、网络都无法联网 找到本机的DNS 找到emu-launch-params.txt&#xff0c;添加DNS -dns-server 192.168.124.1 重启虚拟机&#xff0c;关闭无线

Python使用psycopg2读取PostgreSQL的geometry字段出现二进制乱码

1、问题 读取geometry字段出现二进制乱码 查询语句&#xff1a; sql "select * from public"Note: 这种写法在PostgreSQL中直接查询, 没有问题&#xff0c;不会报错。 但是在Python中查询&#xff0c;如果导出的geom还是一长串的geometry 格式的话&#xff0c; …