树形结构的处理——组合模式(一)

树形结构的处理——组合模式(一)

树形结构在软件中随处可见,例如操作系统中的目录结构、应用软件中的菜单、办公系统中的公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题,组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,也可以一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点)。下面将学习这种用于处理树形结构的组合模式。

11.1 设计杀毒软件的框架结构

Sunny软件公司欲开发一个杀毒(AntiVirus)软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现需要提供该杀毒软件的整体框架设计方案。

在介绍Sunny公司开发人员提出的初始解决方案之前,我们先来分析一下操作系统中的文件目录结构,例如在Windows操作系统中,存在如图11-1所示目录结构:

树形结构的处理——组合模式(一) - 图1

图11-1 Windows目录结构

图11-1可以简化为如图11-2所示树形目录结构:

树形结构的处理——组合模式(一) - 图2

图11-2 树形目录结构示意图

我们可以看出,在图11-2中包含文件(灰色节点)和文件夹(白色节点)两类不同的元素,其中在文件夹中可以包含文件,还可以继续包含子文件夹,但是在文件中不能再包含子文件或者子文件夹。在此,我们可以称文件夹为容器(Container),而不同类型的各种文件是其成员,也称为叶子(Leaf),一个文件夹也可以作为另一个更大的文件夹的成员。如果我们现在要对某一个文件夹进行操作,如查找文件,那么需要对指定的文件夹进行遍历,如果存在子文件夹则打开其子文件夹继续遍历,如果是文件则判断之后返回查找结果。

Sunny软件公司的开发人员通过分析,决定使用面向对象的方式来实现对文件和文件夹的操作,定义了如下图像文件类ImageFile、文本文件类TextFile和文件夹类Folder:

  1. //为了突出核心框架代码,我们对杀毒过程的实现进行了大量简化
  2. import java.util.*;
  3. //图像文件类
  4. class ImageFile {
  5. private String name;
  6. public ImageFile(String name) {
  7. this.name = name;
  8. }
  9. public void killVirus() {
  10. //简化代码,模拟杀毒
  11. System.out.println("----对图像文件'" + name + "'进行杀毒");
  12. }
  13. }
  14. //文本文件类
  15. class TextFile {
  16. private String name;
  17. public TextFile(String name) {
  18. this.name = name;
  19. }
  20. public void killVirus() {
  21. //简化代码,模拟杀毒
  22. System.out.println("----对文本文件'" + name + "'进行杀毒");
  23. }
  24. }
  25. //文件夹类
  26. class Folder {
  27. private String name;
  28. //定义集合folderList,用于存储Folder类型的成员
  29. private ArrayList<Folder> folderList = new ArrayList<Folder>();
  30. //定义集合imageList,用于存储ImageFile类型的成员
  31. private ArrayList<ImageFile> imageList = new ArrayList<ImageFile>();
  32. //定义集合textList,用于存储TextFile类型的成员
  33. private ArrayList<TextFile> textList = new ArrayList<TextFile>();
  34. public Folder(String name) {
  35. this.name = name;
  36. }
  37. //增加新的Folder类型的成员
  38. public void addFolder(Folder f) {
  39. folderList.add(f);
  40. }
  41. //增加新的ImageFile类型的成员
  42. public void addImageFile(ImageFile image) {
  43. imageList.add(image);
  44. }
  45. //增加新的TextFile类型的成员
  46. public void addTextFile(TextFile text) {
  47. textList.add(text);
  48. }
  49. //需提供三个不同的方法removeFolder()、removeImageFile()和removeTextFile()来删除成员,代码省略
  50. //需提供三个不同的方法getChildFolder(int i)、getChildImageFile(int i)和getChildTextFile(int i)来获取成员,代码省略
  51. public void killVirus() {
  52. System.out.println("****对文件夹'" + name + "'进行杀毒"); //模拟杀毒
  53. //如果是Folder类型的成员,递归调用Folder的killVirus()方法
  54. for(Object obj : folderList) {
  55. ((Folder)obj).killVirus();
  56. }
  57. //如果是ImageFile类型的成员,调用ImageFile的killVirus()方法
  58. for(Object obj : imageList) {
  59. ((ImageFile)obj).killVirus();
  60. }
  61. //如果是TextFile类型的成员,调用TextFile的killVirus()方法
  62. for(Object obj : textList) {
  63. ((TextFile)obj).killVirus();
  64. }
  65. }
  66. }

编写如下客户端测试代码进行测试:

  1. class Client {
  2. public static void main(String args[]) {
  3. Folder folder1,folder2,folder3;
  4. folder1 = new Folder("Sunny的资料");
  5. folder2 = new Folder("图像文件");
  6. folder3 = new Folder("文本文件");
  7. ImageFile image1,image2;
  8. image1 = new ImageFile("小龙女.jpg");
  9. image2 = new ImageFile("张无忌.gif");
  10. TextFile text1,text2;
  11. text1 = new TextFile("九阴真经.txt");
  12. text2 = new TextFile("葵花宝典.doc");
  13. folder2.addImageFile(image1);
  14. folder2.addImageFile(image2);
  15. folder3.addTextFile(text1);
  16. folder3.addTextFile(text2);
  17. folder1.addFolder(folder2);
  18. folder1.addFolder(folder3);
  19. folder1.killVirus();
  20. }
  21. }

编译并运行程序,输出结果如下:

  1. ****对文件夹'Sunny的资料'进行杀毒
  2. ****对文件夹'图像文件'进行杀毒
  3. ----对图像文件'小龙女.jpg'进行杀毒
  4. ----对图像文件'张无忌.gif'进行杀毒
  5. ****对文件夹'文本文件'进行杀毒
  6. ----对文本文件'九阴真经.txt'进行杀毒
  7. ----对文本文件'葵花宝典.doc'进行杀毒

Sunny公司开发人员“成功”实现了杀毒软件的框架设计,但通过仔细分析,发现该设计方案存在如下问题:

(1) 文件夹类Folder的设计和实现都非常复杂,需要定义多个集合存储不同类型的成员,而且需要针对不同的成员提供增加、删除和获取等管理和访问成员的方法,存在大量的冗余代码,系统维护较为困难;

(2) 由于系统没有提供抽象层,客户端代码必须有区别地对待充当容器的文件夹Folder和充当叶子的ImageFile和TextFile,无法统一对它们进行处理;

(3) 系统的灵活性和可扩展性差,如果需要增加新的类型的叶子和容器都需要对原有代码进行修改,例如如果需要在系统中增加一种新类型的视频文件VideoFile,则必须修改Folder类的源代码,否则无法在文件夹中添加视频文件。

面对以上问题,Sunny软件公司的开发人员该如何来解决?这就需要用到本章将要介绍的组合模式,组合模式为处理树形结构提供了一种较为完美的解决方案,它描述了如何将容器和叶子进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待容器和叶子。

  • 书签
  • 添加书签 移除书签
  • Introduction
  • 基础知识
    • 设计模式概述
      • 从招式与内功谈起——设计模式概述(一)
      • 从招式与内功谈起——设计模式概述(二)
      • 从招式与内功谈起——设计模式概述(三)
    • 面向对象设计原则
      • 面向对象设计原则之单一职责原则
      • 面向对象设计原则之开闭原则
      • 面向对象设计原则之里氏代换原则
      • 面向对象设计原则之依赖倒转原则
      • 面向对象设计原则之接口隔离原则
      • 面向对象设计原则之合成复用原则
      • 面向对象设计原则之迪米特法则
  • 六个创建型模式
    • 简单工厂模式-Simple Factory Pattern
      • 工厂三兄弟之简单工厂模式(一)
      • 工厂三兄弟之简单工厂模式(二)
      • 工厂三兄弟之简单工厂模式(三)
      • 工厂三兄弟之简单工厂模式(四)
    • 工厂方法模式-Factory Method Pattern
      • 工厂三兄弟之工厂方法模式(一)
      • 工厂三兄弟之工厂方法模式(二)
      • 工厂三兄弟之工厂方法模式(三)
      • 工厂三兄弟之工厂方法模式(四)
    • 抽象工厂模式-Abstract Factory Pattern
      • 工厂三兄弟之抽象工厂模式(一)
      • 工厂三兄弟之抽象工厂模式(二)
      • 工厂三兄弟之抽象工厂模式(三)
      • 工厂三兄弟之抽象工厂模式(四)
      • 工厂三兄弟之抽象工厂模式(五)
    • 单例模式-Singleton Pattern
      • 确保对象的唯一性——单例模式 (一)
      • 确保对象的唯一性——单例模式 (二)
      • 确保对象的唯一性——单例模式 (三)
      • 确保对象的唯一性——单例模式 (四)
      • 确保对象的唯一性——单例模式 (五)
    • 原型模式-Prototype Pattern
      • 对象的克隆——原型模式(一)
      • 对象的克隆——原型模式(二)
      • 对象的克隆——原型模式(三)
      • 对象的克隆——原型模式(四)
    • 建造者模式-Builder Pattern
      • 复杂对象的组装与创建——建造者模式(一)
      • 复杂对象的组装与创建——建造者模式(二)
      • 复杂对象的组装与创建——建造者模式(三)
  • 七个结构型模式
    • 适配器模式-Adapter Pattern
      • 不兼容结构的协调——适配器模式(一)
      • 不兼容结构的协调——适配器模式(二)
      • 不兼容结构的协调——适配器模式(三)
      • 不兼容结构的协调——适配器模式(四)
    • 桥接模式-Bridge Pattern
      • 处理多维度变化——桥接模式(一)
      • 处理多维度变化——桥接模式(二)
      • 处理多维度变化——桥接模式(三)
      • 处理多维度变化——桥接模式(四)
    • 组合模式-Composite Pattern
      • 树形结构的处理——组合模式(一)
      • 树形结构的处理——组合模式(二)
      • 树形结构的处理——组合模式(三)
      • 树形结构的处理——组合模式(四)
      • 树形结构的处理——组合模式(五)
    • 装饰模式-Decorator Pattern
      • 扩展系统功能——装饰模式(一)
      • 扩展系统功能——装饰模式(二)
      • 扩展系统功能——装饰模式(三)
      • 扩展系统功能——装饰模式(四)
    • 外观模式-Facade Pattern
      • 深入浅出外观模式(一)
      • 深入浅出外观模式(二)
      • 深入浅出外观模式(三)
    • 享元模式-Flyweight Pattern
      • 实现对象的复用——享元模式(一)
      • 实现对象的复用——享元模式(二)
      • 实现对象的复用——享元模式(三)
      • 实现对象的复用——享元模式(四)
      • 实现对象的复用——享元模式(五)
    • 代理模式-Proxy Pattern
      • 设计模式之代理模式(一)
      • 设计模式之代理模式(二)
      • 设计模式之代理模式(三)
      • 设计模式之代理模式(四)
  • 十一个行为型模式
    • 职责链模式-Chain of Responsibility Pattern
      • 请求的链式处理——职责链模式(一)
      • 请求的链式处理——职责链模式(二)
      • 请求的链式处理——职责链模式(三)
      • 请求的链式处理——职责链模式(四)
    • 命令模式-Command Pattern
      • 请求发送者与接收者解耦——命令模式(一)
      • 请求发送者与接收者解耦——命令模式(二)
      • 请求发送者与接收者解耦——命令模式(三)
      • 请求发送者与接收者解耦——命令模式(四)
      • 请求发送者与接收者解耦——命令模式(五)
      • 请求发送者与接收者解耦——命令模式(六)
    • 解释器模式-Interpreter Pattern
      • 自定义语言的实现——解释器模式(一)
      • 自定义语言的实现——解释器模式(二)
      • 自定义语言的实现——解释器模式(三)
      • 自定义语言的实现——解释器模式(四)
      • 自定义语言的实现——解释器模式(五)
      • 自定义语言的实现——解释器模式(六)
    • 迭代器模式-Iterator Pattern
      • 遍历聚合对象中的元素——迭代器模式(一)
      • 遍历聚合对象中的元素——迭代器模式(二)
      • 遍历聚合对象中的元素——迭代器模式(三)
      • 遍历聚合对象中的元素——迭代器模式(四)
      • 遍历聚合对象中的元素——迭代器模式(五)
      • 遍历聚合对象中的元素——迭代器模式(六)
    • 中介者模式-Mediator Pattern
      • 协调多个对象之间的交互——中介者模式(一)
      • 协调多个对象之间的交互——中介者模式(二)
      • 协调多个对象之间的交互——中介者模式(三)
      • 协调多个对象之间的交互——中介者模式(四)
      • 协调多个对象之间的交互——中介者模式(五)
    • 备忘录模式-Memento Pattern
      • 撤销功能的实现——备忘录模式(一)
      • 撤销功能的实现——备忘录模式(二)
      • 撤销功能的实现——备忘录模式(三)
      • 撤销功能的实现——备忘录模式(四)
      • 撤销功能的实现——备忘录模式(五)
    • 观察者模式-Observer Pattern
      • 对象间的联动——观察者模式(一)
      • 对象间的联动——观察者模式(二)
      • 对象间的联动——观察者模式(三)
      • 对象间的联动——观察者模式(四)
      • 对象间的联动——观察者模式(五)
      • 对象间的联动——观察者模式(六)
    • 状态模式-State Pattern
      • 处理对象的多种状态及其相互转换——状态模式(一)
      • 处理对象的多种状态及其相互转换——状态模式(二)
      • 处理对象的多种状态及其相互转换——状态模式(三)
      • 处理对象的多种状态及其相互转换——状态模式(四)
      • 处理对象的多种状态及其相互转换——状态模式(五)
      • 处理对象的多种状态及其相互转换——状态模式(六)
    • 策略模式-Strategy Pattern
      • 算法的封装与切换——策略模式(一)
      • 算法的封装与切换——策略模式(二)
      • 算法的封装与切换——策略模式(三)
      • 算法的封装与切换——策略模式(四)
    • 模板方法模式-Template Method Pattern
      • 模板方法模式深度解析(一)
      • 模板方法模式深度解析(二)
      • 模板方法模式深度解析(三)
    • 访问者模式-Visitor Pattern
      • 操作复杂对象结构——访问者模式(一)
      • 操作复杂对象结构——访问者模式(二)
      • 操作复杂对象结构——访问者模式(三)
      • 操作复杂对象结构——访问者模式(四)
  • 设计模式趣味学习(复习)
    • 设计模式与足球(一)
    • 设计模式与足球(二)
    • 设计模式与足球(三)
    • 设计模式与足球(四)
  • 设计模式综合应用实例
    • 多人联机射击游戏
      • 多人联机射击游戏中的设计模式应用(一)
      • 多人联机射击游戏中的设计模式应用(二)
    • 数据库同步系统
      • 设计模式综合实例分析之数据库同步系统(一)
      • 设计模式综合实例分析之数据库同步系统(二)
      • 设计模式综合实例分析之数据库同步系统(三)
暂无相关搜索结果!

    代做工资流水公司宿迁查企业对公流水中山签证银行流水 费用新乡贷款流水公司三亚对公账户流水办理桂林消费贷流水价格贵阳银行流水单费用孝感车贷银行流水 公司洛阳办理转账流水淮安打印车贷流水烟台代做车贷工资流水江门银行流水多少钱北京查询在职证明海口背调流水成都车贷流水威海流水九江办签证工资流水芜湖签证流水报价揭阳银行流水电子版制作泉州办理签证流水保定对公账户流水报价赣州工资流水app截图办理蚌埠开对公账户流水合肥购房银行流水价格湘潭企业贷流水多少钱台州查询工资代付流水徐州工作收入证明查询泉州打印入职流水上海公司流水制作廊坊查公司银行流水苏州查银行流水PS香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

    代做工资流水公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化