• js中的设计模式之组合模式


    Js中的组合模式

    定义

    是一种将对象组合成树状结构的层次结构模式,用来表示 整体-部分 的关系,使用用户对单个对象和组合对象具有一致的访问性。

    详细描述

    组合模式是一个树形结构,里面的数据可以是单个对象,也可以n个单个对象组合起来的组合对象。

    组合模式主要是用来表示 部分-整体的关系,也就是说组合模式下对于调用者角度来看调用一个对象和调用组合对象没有什么区别,将复杂的组合对象用处理单个对象的方式就可以完成,解耦了客户程序与复杂组合对象的解耦。

    因为单个对象就可以表现组合对象,所以要求组合模式中的单个对象和组合对象必须暴露出相同的方法让客户来调用。

    示例图

    在这里插入图片描述

    如上图所示当用户需要调用整个对象时,此时因为单个对象和组合对象暴露的调用方法一致,所以用户只需要调用一次最上层的组合对象,组合对象就会将调用逐级往下传递并执行调用,这样用户就可以非常轻松的处理完复杂的组合对象数据。

    应用场景

    用于想表示部分-整体层次结构,用户可以忽略单个对象与组合对象的不同。
    如: 树形结构菜单、文件,文件夹的处理等。

    代码实例

    宏命令改写
    在命令模式中我们写过宏命令的代码(命令模式),此时只需要拿来将命令修改为同样的名字就完成了一个最简单的组合模式:

    
    
      
        
        
        
        Document
      
      
        
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    上述代码中组合对象macroCommand 由三个单独对象组合而成,他们都暴漏出相同执行命令的方法execute ,调用者只调用最顶层的组合对象macroCommand就相当于调用了整个组合对象。上面只是最简单的对象组合下面我们看下更复杂对象的组合实例:

    
    
      
        
        
        
        Document
      
      
        
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    上述组合对象示例图:
    在这里插入图片描述
    上述代码就是更加复杂一些的组合对象macroCommand 它的组成不但包含单个对象还包含了组合对象back 还包含了组合对象macroCommand1和macroCommand2,但是对于调用者来着没有任何区别只需要调用macroCommand对象的execute方法就可以轻松的调用整个组合对象中的每个执行。此时如果需要添加新的执行和组合对象只需要暴露出和原结构相同的execute方法即可(参考在下面文件夹实例),非常易于维护和扩展。

    文件处理

    文件夹和文件之间的关系,非常适合用组合模式来描述。文件夹里既可以包含文件,又可以 包含其他文件夹,最终可能组合成一棵树。下面看下扫描文件的实例:

    class Folder {
      constructor(name) {
        this.name = name;
        this.list = [];
      }
    
      // 扫描
      scean() {
        console.log('开始扫描文件夹 -->' + this.name);
        this.list.forEach((file) => file.scean());
      }
    
      // 添加
      add(file) {
        this.list.push(file);
      }
    }
    
    class File {
      constructor(name) {
        this.name = name;
      }
    
      scean() {
        console.log('开始扫描文件 -->' + this.name);
      }
    
      // 防止单个对象误操作,添加提示解决透明性带来的安全问题
      add() {
        throw new Error('文件下面不能再添加文件');
      }
    }
    
    // 定义文件夹
    const folder = new Folder('学习资料');
    const folder1 = new Folder('JavaScript');
    const folder2 = new Folder('jQuery');
    
    // 定义文件
    const file1 = new File('JavaScript 设计模式与开发实践');
    const file2 = new File('精通 jQuery');
    const file3 = new File('重构与模式');
    
    folder1.add(file1);
    folder2.add(file2);
    folder.add(folder1);
    folder.add(folder2);
    folder.add(file3);
    
    // 下面将其他文件夹和其下面的文件移动到添加好的文件夹folder中(扩展组合对象中的数据)
    const folder3 = new Folder('Nodejs');
    const file4 = new File('深入浅出 Node.js');
    folder3.add(file4);
    const file5 = new File('JavaScript 语言精髓与编程实践');
    
    folder.add(folder3);
    folder.add(file5);
    
    // 最后开始扫描整个文件目录
    folder.scean();
    
    // 扫描结果
    // 开始扫描文件夹 -->学习资料
    // 开始扫描文件夹 -->JavaScript
    // 开始扫描文件 -->JavaScript 设计模式与开发实践
    // 开始扫描文件夹 -->jQuery
    // 开始扫描文件 -->精通 jQuery
    // 开始扫描文件 -->重构与模式
    // 开始扫描文件夹 -->Nodejs
    // 开始扫描文件 -->深入浅出 Node.js
    // 开始扫描文件 -->JavaScript 语言精髓与编程实践
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    上述代码更加清晰的展现了组合模式中 部分-整体原则,用户不用区分文件和文件夹的区别,直接调用scean方法就可以完成整个文件目录的扫描。 而当我们想要添加文件数据的时候,只需要直接调用原来的方法添加,不需要改动代码就可以完成。

    总结

    通过上述实例我们可以看到组合模式表示部分-整体的特性,所以我们在维护这些特性的时候就必须要保持单个对象与组合对象的一致性。

    正因为部分与整体的一致性,所以组合模式具有调用非常简单,数据扩展更加灵活的特点。

    同时在保持灵活,简单优点的时候因为单个对象和组合对象几乎一样,会使代码不易于阅读,并且由于创建了太多的对象可能会增加系统开销问题。

  • 相关阅读:
    oracle 数据链接过多,导致后续链接链接不上
    解析人工智能管理对社会生产力的发展
    dockerfile避坑笔记(VMWare下使用Ubuntu在Ubuntu20.04基础镜像下docker打包多个go项目)
    官方烧录软件烧写2023.10版本树莓派镜像
    【Vue-Demo】倒计时3秒后返回首页
    Scrum 框架的四个会议还适用于哪些敏捷方法?
    线程池相关总结
    【机器学习可解释性】1.模型洞察的价值
    JZ04 [剑指 Offer 04] 二维数组中的查找
    Seal库官方示例(五):ckks_basics.cpp解析
  • 原文地址:https://blog.csdn.net/weixin_43911758/article/details/126520352