zoukankan      html  css  js  c++  java
  • 组合模式-统一的处理个别对象与组合对象

    公号:码农充电站pro
    主页:https://codeshellme.github.io

    本篇来介绍组合模式Composite Design Pattern)。

    1,组合模式

    组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。

    如果对象之间呈树形结构,是一种部分与整体的关系,这种情况都比较适合用组合模式。

    组合模式构建的树状关系如下所示:

    在这里插入图片描述

    组合模式使得我们构建这种树状关系变得极为简单。aComposite 是组合对象,aLeaf 是个体对象。组合对象中可以嵌套组合对象和个体对象,个体对象中不能再包含其它对象。

    因为组合对象中可以再次嵌套组合对象,所以组合模式也是一种递归关系

    组合模式的类图如下:

    在这里插入图片描述

    从类图中可以看到,Component 为所有的对象提供了统一的接口。组合对象中有 addremove 操作,说明组合对象中可以添加和删除组合对象与个体对象。

    注意 Leaf 节点中只有 operation 操作,因为 Leaf 节点不能再嵌套其它节点。

    组合对象和个体对象中都有 operation 操作,使得我们能够把相同的操作应用在组合对象和个别对象上。

    2,组合模式示例

    下面举个例子,来看下如何使用组合模式。

    我们已经知道,组合模式非常适合表示树形结构,而 Linux 目录结构就是一个树形结构。下面就用组合模式来构建目录结构。

    我们知道目录中即可包含目录,也可包含文件。根据组合模式的类图,可设计出下面的 Linux 文件系统类图:

    在这里插入图片描述

    文件系统可以包括文件和目录,目录中可以嵌套目录和文件,而文件中不能再嵌套其它东西。所以,File 类中没有 addremove 方法。

    首先创建 FileSystem 抽象类:

    abstract class FileSystem {
        protected String path;
    
        public abstract void printFile();
    }
    

    printFile 方法用于输出文件名。

    再创建 File 类:

    class File extends FileSystem {
        public File(String path) {
            this.path = path;
        }
    
        public void printFile() {
            System.out.println(path);
        }
    }
    

    File 类继承了 FileSystem, 因为 File 类本身就是文件,所以它的 printFile 非常简单。

    再创建 Directory 类:

    class Directory extends FileSystem {
        private List<FileSystem> nodes; // 用于存储节点
    
        public Directory(String path) {
            this.path = path;
            this.nodes = new ArrayList<>();
        }
    
        public void printFile() {
            System.out.println(path);
    
    		// 递归输出目录和文件
            for (FileSystem node: nodes) {
                node.printFile();
            }
        }
    
        public void addNode(FileSystem node) {
            nodes.add(node);
        }
    
        public void removeNode(FileSystem node) {
            nodes.remove(node);
        }
    }
    

    注意区分 File 类和 Directory 类的不同。

    下面来测试代码,假设我们要构建这样的目录结构:

    test/
    ├── a
    ├── b
    │   ├── 1.txt
    │   └── d
    │       └── 2.txt
    └── c
        └── 3.txt
    

    首先创建文件节点和目录节点:

    // 创建文件节点
    File txt1 = new File("test/b/1.txt");
    File txt2 = new File("test/b/d/2.txt");
    File txt3 = new File("test/c/3.txt");
    
    // 创建目录节点
    Directory test = new Directory("test/");
    Directory a = new Directory("test/a/");
    Directory b = new Directory("test/b/");
    Directory c = new Directory("test/c/");
    Directory d = new Directory("test/b/d/");
    

    构建目录结构:

    // 构造目录结构
    test.addNode(a);
    test.addNode(b);
    test.addNode(c);
    
    b.addNode(txt1);
    b.addNode(d);
    
    c.addNode(txt3);
    d.addNode(txt2);
    

    输出 test 目录:

    test.printFile();
    

    结果如下:

    test/
    test/a/
    test/b/
    test/b/1.txt
    test/b/d/
    test/b/d/2.txt
    test/c/
    test/c/3.txt
    

    输出 b 目录:

    b.printFile();
    

    结果如下:

    test/b/
    test/b/1.txt
    test/b/d/
    test/b/d/2.txt
    

    删除 b 目录后,在输出 test 目录:

    test.removeNode(b);
    test.printFile();
    

    结果如下:

    test/
    test/a/
    test/c/
    test/c/3.txt
    

    通过测试结果可以看到,我们构建的目录结构是没有问题的。

    我将完整的代码放在了这里,供大家参考。

    3,总结

    组合模式将一组对象组织成树形结构,对象分为个体对象和组合对象,组合对象中可以包含个体对象和组合对象。组合模式会以递归的方式来处理树的节点。

    使用组合模式的前提是,对象之间的关系要符合树形结构的特点。组合模式使得处理树形结构的对象关系变得非常简单。

    (本节完。)


    推荐阅读:

    外观模式-简化子系统的复杂性

    模板方法模式-封装一套算法流程

    迭代器模式-统一集合的遍历方式

    状态模式-将状态和行为封装成对象

    代理模式-访问对象的代理而非其本身


    欢迎关注作者公众号,获取更多技术干货。

    码农充电站pro

  • 相关阅读:
    JAVA maven 仓库 基础命令
    JAVA maven 环境变量配置
    JAVA jdk 环境变量配置
    kafka 环境搭建
    java servlet 基础
    java idea 配置tomcat
    java tomcat服务器
    java io流
    java 字符流
    【火炉炼AI】深度学习005-简单几行Keras代码解决二分类问题
  • 原文地址:https://www.cnblogs.com/codeshell/p/14270915.html
Copyright © 2011-2022 走看看