Java设计模式(十七)—— 组合模式

        组合模式的定义如下:将对象组合成树形结构以表示“部分-整体”的层次结构,让用户对单个对象和组合对象的使用具有一致性。

适用组合模式的情景如下:

  • 希望表示对象的“部分—整体”层次结构
  • 希望用户用一致方式处理个体和组合对象

一、问题的提出

我们研究的问题有许多树形结构的问题,例如文件结构:

 例如,要用程序创建文件结构,为了验证正确与否,还要再控制台上输出从某目录开始的所有文件信息。文件树形结构可以分为两类,一类是文件叶子节点,无后继节点,一类是中间目录节点,有后继节点。具体代码如下:

(1)文件节点类

public class FileLeaf {
    String fileName;

    public FileLeaf(String fileName) {
        this.fileName = fileName;
    }
    public void display() {
        System.out.println(fileName);
    }
}

(2)中间目录节点类 DirectNode

public class DirectNode {
    String nodeName;

    public DirectNode(String nodeName) {
        this.nodeName = nodeName;
    }
    //后继目录集合
    ArrayList<DirectNode> nodeList = new ArrayList<>();
    //当前目录文件集合
    ArrayList<FileLeaf> fileList = new ArrayList<>();
    //添加下一级子目录
    public void addNode(DirectNode node ) {
        nodeList.add(node);
    }
    //添加本级文件
    public void addLeaf(FileLeaf leaf) {
        fileList.add(leaf);
    }
    //从本级目录开始显示
    public void display() {
        for (int i = 0; i < fileList.size(); i++) {
            fileList.get(i).display();
        }
        for (int i = 0; i < nodeList.size(); i++) {
            System.out.println(nodeList.get(i).nodeName);
            nodeList.get(i).display();
        }
    }
}

(3)测试类

public class Test {
    public static void createTree(DirectNode node) {
        File f = new File(node.nodeName);
        File f2[] = f.listFiles();
        for (int i = 0; i < f2.length; i++) {
            //如果是文件类型,则把他添加到当前目录文件集合
            if (f2[i].isFile()) {
                FileLeaf l = new FileLeaf(f2[i].getAbsolutePath());
                node.addLeaf(l);
            }
            //如果是目录类型,则把他添加到目录集合,然后继续递归添加
            if (f2[i].isDirectory()) {
                DirectNode node2 = new DirectNode(f2[i].getAbsolutePath());
                node.addNode(node2);
                createTree(node2);
            }
        }
    }

    public static void main(String[] args) {
        DirectNode start = new DirectNode("D:\\学习笔记\\Linux\\docker-book-master\\docker");
        createTree(start);
        start.display();
    }
}

二、组合模式

        从上面图片可知:根目录是由两个子目录组成的;第一个子目录由两个文件组成;第二个子目录也由两个文件组成,因此树形形式也可以叫做组合模式。

        在图中,把节点分为叶子节点与目录节点,它们是孤立的。然后把叶子节点与目录节点都看成相同性质的节点,只不过目录节点的后继节点不为空,而叶子节点的后继节点为null。这样就能够对树形结构的所有节点执行相同的操作,这也是组合模式最大的特点。

采用组合模式修改上面例子的功能:

(1)定义抽象节点类Node

该类是叶子节点与目录节点的父类,节点名称是name。其主要包括两类方法:一类方法是所有节点具有相同形式、不同内容的方法。这类方法要定义成抽象方法,如display();另一类方法是目录节点必须重写,而叶子节点不需要重写的方法,相当于为叶子节点提供了默认实现,如addNode()方法。因为叶子对象没有该功能,所以可以通过抛出异常防止叶子节点无效调用该方法。/

public abstract class Node {
    protected String name;
    public Node(String name) {
        this.name = name;
    }
    public void addNode(Node node) throws Exception {
        throw new Exception("无效的异常");
    }
    abstract void display();
}

(2)文件叶子节点类 FileNode

public class FileNode extends Node{
    public FileNode(String name) {
        super(name);
    }
    @Override
    void display() {
        System.out.println(name);
    }
}

(3)目录节点类 DirectNode

        该类从Node抽象类派生后,与原DirectNode类相比,主要有以下不同:

  • 由定义两个结合类成员变量转为定义一个集合类成员变量nodeList
  • 由定义两个添加方法转为定义一个添加方法addNode()
  • display() 方法中,由两个不同元素的循环转为一个对相同性质节点Node循环。
public class DirectNode2 extends Node{
    private ArrayList<Node> nodeList = new ArrayList<>();
    public DirectNode2(String name) {
        super(name);
    }
    public void addNode(Node node) throws Exception {
        nodeList.add(node);
    }
    @Override
    void display() {
        System.out.println(name);
        for (int i = 0; i < nodeList.size(); i++) {
            nodeList.get(i).display();
        }
    }
}

(4) 测试类

public class Test2 {
    public static void createTree(Node node) throws Exception {
        File f = new File(node.name);
        File f2[] = f.listFiles();
        for (int i = 0; i < f2.length; i++) {
            if (f2[i].isFile()) {
                Node node2 = new FileNode(f2[i].getAbsolutePath());
                node.addNode(node2);
            }
            if (f2[i].isDirectory()) {
                Node node2 = new DirectNode2(f2[i].getAbsolutePath());
                node.addNode(node2);
                createTree(node2);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Node start = new DirectNode2("D:\\学习笔记\\Linux\\docker-book-master\\docker");
        createTree(start);
        start.display();
    }
}

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

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

相关文章

这是一篇能够教会你运营阿里巴巴国际站的文章

对于很多跨境人来说&#xff0c;运营真的是一个让人头疼的大事情。不知道要从哪个方面下手&#xff0c;不知道要往哪方面努力等等问题都是很常见的&#xff0c;所以今天龙哥就解剖一下阿里巴巴国际站的运营方法&#xff0c;简单地给大家讲一下要掌握哪些方面的知识。运营这条路…

【数据结构篇C++实现】- 哈希表

文章目录&#x1f680;一、哈希表的原理精讲&#x1f6a2;&#xff08;一&#xff09;概念&#x1f6a2;&#xff08;二&#xff09;常见哈希函数的构造方法1.直接定址法2.数字分析法3.平方取中法4.除留余数法5.随机数法&#x1f6a2;&#xff08;三&#xff09;哈希冲突与处理…

web服务器—nginx

一、nginx介绍Nginx(“engine x”)是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。和apache一样&#xff0c;都是web服务器软件&#xff0c;因为其性能优异&#xff0c;所以被广大运维喜欢。又因…

【python】【protobuf】逆向还原protobuf结构

文章目录一、前言二、示例三、python demo一、前言 在很多场景&#xff0c;都有一个需求&#xff1a; 得到了一个编码后的protobuf数据&#xff08;比如竞品调研的的数据包&#xff09;&#xff0c;需要逆向还原其proto结构文件。 有3种方案去做这件事情&#xff1a; 从编码入…

Linux常用文件管理命令

Linux常用文件管理命令 目录Linux常用文件管理命令前言常用命令练习题创建文件夹题目代码复制题目代码移动题目代码删除题目代码系列操作题目代码前言 本文将讲解我们在使用Linux操作系统时经常需要使用的命令&#xff0c;也可以当成是一篇笔记的记录&#xff0c;当然光看这些…

Ubuntu安装交叉编译器gcc

1.创建文件并把压缩包复制到文件夹下 2.解压到文件夹下 先找到放置的目录 也可以直接找到文件夹右键-在终端打开 通过-C选项指定解压后的目标目录 tar -jxvf gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.bz2 -C /opt 注意:输入文件名时可以Tab键自动补齐 输入…

计算机网络中端到端与点到点的区别

计算机网络中端到端与点到点的区别 数据传输的可靠性是通过数据链路层和网络层的点对点和传输层的端对端保证的。端到端与点到点是针对网络中传输的两端设备间的关系而言的。 在一个网络系统的不同分层中&#xff0c;可能用到端到端传输&#xff0c;也可能用到点到点传输。如…

限流、熔断、服务降级

在分布式系统中&#xff0c;如果某个服务节点发生故障或者网络发生异常&#xff0c;都有可能导致调用方被阻塞等待&#xff0c;如果超时时间设置很长&#xff0c;调用方资源很可能被耗尽。这又导致了调用方的上游系统发生资源耗尽的情况&#xff0c;最终导致系统雪崩。 举例&a…

[Vulfocus解题系列]Spring WebFlow 远程代码执行漏洞(CVE-2017-4971)

简介 Spring WebFlow 是一个适用于开发基于流程的应用程序的框架&#xff08;如购物逻辑&#xff09;&#xff0c;可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中&#xff0c;如果我们控制了数据绑定时的field&#xff0c;将导致一个SpEL表达式注入漏洞…

科大奥瑞物理实验——声速的测量

实验名称&#xff1a;声速的测量 1. 实验目的&#xff1a; &#xff08;1&#xff09;了解超声波的发射和接收方法。 &#xff08;2&#xff09;加深对振动合成、波动干涉等理论知识的理解。 &#xff08;3&#xff09;掌握用驻波法和相位法测声速。 2. 实验器材&#xff1a…

如何挖掘用户需求的真正动机?关键是4大因素

需求分析实质是挖掘用户内心真正的目标&#xff0c;并转化为产品需求的过程。而用户需求是用户基于自身角度提出的表层需求&#xff0c;这些需求往往有用户期望的产品功能指向。而在产品功能指向的背后&#xff0c;暗藏着潜在的用户动机&#xff0c;这是用户真正希望解决的核心…

【尚硅谷】Java数据结构与算法笔记13 - 图

文章目录一、图的基本介绍1.1 为什么要有图1.2 图的举例说明1.3 图的常用概念二、图的表示方式2.1 邻接矩阵2.2 邻接表三、图的快速入门案例四、图的遍历4.1 深度优先遍历 DFS4.1.1 基本思想4.1.2 算法步骤4.1.3 图示4.2 广度优先遍历 BFS4.2.1 基本思想4.2.2 算法步骤4.2.3 图…

【机器学习】P8 过拟合与欠拟合、正则化与正则化后的损失函数和梯度下降

过拟合与欠拟合、正则化与正则化后的损失函数和梯度下降过拟合与欠拟合过拟合与欠拟合直观理解线性回归中 过拟合与欠拟合逻辑回归中 过拟合与欠拟合过拟合与欠拟合的解决办法过拟合解决方案欠拟合解决方案包含正则化的损失函数正则化线性回归损失函数正则化逻辑回归损失函数包…

java爬虫利器Jsoup的使用

对于长期使用java做编程的程序猿应该知道&#xff0c;java支持的爬虫框架还是有很多的&#xff0c;如&#xff1a;ebMagic、Spider、Jsoup等。今天我们就用Jsoup来实现一个小小的爬虫程序&#xff0c;Jsoup作为kava的HTML解析器&#xff0c;可以直接对某个URL地址、HTML文本内容…

焦虑真的好吗 过度的焦虑存在哪些影响

日常常见的焦虑情绪真的好吗&#xff1f;焦虑是我们七情中的一种正常情绪表现&#xff0c;我们生活当中很多因素都可能会导致我们产生焦虑的情绪表现&#xff0c;如一场考试、一次挑战、一个活动等等。这种焦虑情绪的产生并不是一件坏事&#xff0c;相反&#xff0c;焦虑情绪的…

ROS学习笔记(零):ROS与机器人概述

ROS学习笔记&#xff08;零&#xff09;&#xff1a;ROS与机器人概述ROSROS的起源ROS的特点ROS架构设计机器人机器人的定义机器人的组成执行机构驱动系统传感系统控制系统ROS ROS的起源 ROS&#xff08;Robot Operating System&#xff09;是一个广泛使用的机器人操作系统&…

Python图片相册批处理器的设计与实现批量添加图片水印、批量命名等功能

课题研究使用Python语言开发一个包含批量添加图片水印、批量命名等功能的图片批处理程序&#xff0c;功能模块大概包含以下模块&#xff1a; &#xff08;1&#xff09;首页模块&#xff1a;首页是整个软件的初始页面&#xff0c;包含用户登录、注册、关于本软件等功能&#xf…

红日(vulnstack)5 内网渗透ATTCK实战

环境配置 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;l8r7 攻击机&#xff1a;kali2022.03 192.168.135.128(NET模式) win7 192.168.138.136 (仅主机模式) 192.168.135.150 (NET模式) win2008 192.168.138.138 (仅主机模式) web渗透 1.nmap探测目标靶机开…

Qt学习笔记之SQLITE数据库

1. SQLite数据库介绍 SQLite&#xff0c;是一款轻型的数据库&#xff0c;是遵守ACID的关系型数据库管理系统&#xff0c;它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的&#xff0c;而且已经在很多嵌入式产品中使用了它&#xff0c;…

SpringBoot(1)基础入门

SpringBoot基础入门SpringBoot项目创建方式Idea创建SpringBoot官网创建基于阿里云创建项目手工搭建SpringBoot启动parentstarter引导类内嵌tomcat基础配置属性配置配置文件分类yaml文件yaml数据读取整合第三方技术整合JUnit整合MyBatis整合Mybatis-Plus整合DruidSpringBoot是由…