找回密码
 立即注册
首页 业界区 业界 设计模式(八)组合

设计模式(八)组合

少琼 2025-6-9 05:18:24
一、定义

组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。组合模式是一种结构型模式。
二、描述

包含以下三个角色:
1.png
1、Component(抽象构件):它可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,例如增加子构件、删除子构件、获取子构件等。
2、Leaf(叶子构件):它在组合结构中表示叶子结点对象,叶子结点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过抛出异常、提示错误等方式进行处理。
3、Composite(容器构件):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子结点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。
三、例子

X公司想要开发一个杀毒软件,该软件既可以针对某个文件夹杀毒,也可以针对某个指定的文件进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。
2.png
AbstractFile:抽象文件类,充当抽象构件
  1. public abstract class AbstractFile
  2. {
  3.     public abstract void Add(AbstractFile file);
  4.     public abstract void Remove(AbstractFile file);
  5.     public abstract AbstractFile GetChild(int index);
  6.     public abstract void KillVirus();
  7. }
复制代码
ImageFile、VideoFile、TextFile:图像文件、视频文件、文本文件类,充当叶子构件
  1. public class ImageFile : AbstractFile
  2. {
  3.     private string name;
  4.     public ImageFile(string name)
  5.     {
  6.         this.name = name;
  7.     }
  8.     public override void Add(AbstractFile file)
  9.     {
  10.         Console.WriteLine("对不起,系统不支持该方法!");
  11.     }
  12.     public override void Remove(AbstractFile file)
  13.     {
  14.         Console.WriteLine("对不起,系统不支持该方法!");
  15.     }
  16.     public override AbstractFile GetChild(int index)
  17.     {
  18.         Console.WriteLine("对不起,系统不支持该方法!");
  19.         return null;
  20.     }
  21.     public override void KillVirus()
  22.     {
  23.         // 此处模拟杀毒操作
  24.         Console.WriteLine("**** 对图像文件‘{0}’进行杀毒", name);
  25.     }
  26. }
  27. public class TextFile : AbstractFile
  28. {
  29.     private string name;
  30.     public TextFile(string name)
  31.     {
  32.         this.name = name;
  33.     }
  34.     public override void Add(AbstractFile file)
  35.     {
  36.         Console.WriteLine("对不起,系统不支持该方法!");
  37.     }
  38.     public override void Remove(AbstractFile file)
  39.     {
  40.         Console.WriteLine("对不起,系统不支持该方法!");
  41.     }
  42.     public override AbstractFile GetChild(int index)
  43.     {
  44.         Console.WriteLine("对不起,系统不支持该方法!");
  45.         return null;
  46.     }
  47.     public override void KillVirus()
  48.     {
  49.         // 此处模拟杀毒操作
  50.         Console.WriteLine("**** 对文本文件‘{0}’进行杀毒", name);
  51.     }
  52. }
  53. public class VideoFile : AbstractFile
  54. {
  55.     private string name;
  56.     public VideoFile(string name)
  57.     {
  58.         this.name = name;
  59.     }
  60.     public override void Add(AbstractFile file)
  61.     {
  62.         Console.WriteLine("对不起,系统不支持该方法!");
  63.     }
  64.     public override void Remove(AbstractFile file)
  65.     {
  66.         Console.WriteLine("对不起,系统不支持该方法!");
  67.     }
  68.     public override AbstractFile GetChild(int index)
  69.     {
  70.         Console.WriteLine("对不起,系统不支持该方法!");
  71.         return null;
  72.     }
  73.     public override void KillVirus()
  74.     {
  75.         // 此处模拟杀毒操作
  76.         Console.WriteLine("**** 对视频文件‘{0}’进行杀毒", name);
  77.     }
  78. }
复制代码
Folder:文件夹类,充当容器构件
  1. public class Folder : AbstractFile
  2. {
  3.     private IList fileList = new List();
  4.     private string name;
  5.     public Folder(string name)
  6.     {
  7.         this.name = name;
  8.     }
  9.     public override void Add(AbstractFile file)
  10.     {
  11.         fileList.Add(file);
  12.     }
  13.     public override void Remove(AbstractFile file)
  14.     {
  15.         fileList.Remove(file);
  16.     }
  17.     public override AbstractFile GetChild(int index)
  18.     {
  19.         return fileList[index];
  20.     }
  21.     public override void KillVirus()
  22.     {
  23.         // 此处模拟杀毒操作
  24.         Console.WriteLine("---- 对文件夹‘{0}’进行杀毒", name);
  25.         foreach (var item in fileList)
  26.         {
  27.             item.KillVirus();
  28.         }
  29.     }
  30. }
复制代码
Program:测试代码
  1. AbstractFile folder1 = new Folder("EDC的资料");
  2. AbstractFile folder2 = new Folder("图像文件");
  3. AbstractFile folder3 = new Folder("文本文件");
  4. AbstractFile folder4 = new Folder("视频文件");
  5. AbstractFile image1 = new ImageFile("小龙女.jpg");
  6. AbstractFile image2 = new ImageFile("张无忌.gif");
  7. AbstractFile text1 = new TextFile("九阴真经.txt");
  8. AbstractFile text2 = new TextFile("葵花宝典.doc");
  9. AbstractFile video1 = new VideoFile("笑傲江湖.rmvb");
  10. AbstractFile video2 = new VideoFile("天龙八部.mp4");
  11. folder2.Add(image1);
  12. folder2.Add(image2);
  13. folder3.Add(text1);
  14. folder3.Add(text2);
  15. folder4.Add(video1);
  16. folder4.Add(video2);
  17. folder1.Add(folder2);
  18. folder1.Add(folder3);
  19. folder1.Add(folder4);
  20. folder1.KillVirus();
复制代码
3.png

四、总结

1、优点

(1)可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使客户忽略了层次的差异,方便对整个层次结构进行控制。
(2)客户端可以一致地使用一个组合结构或其中单个对象,不必关心是单个对象还是整个结构,简化代码。
(3)增加新的容器构件和叶子构件都十分方便,无需对现有类库代码进行任何修改,符合开闭原则。
(4)为树形结构的面向对象实现提供了灵活地解决方案,可以形成复杂的树形结构,但对树形结构的控制却很简单。
2、缺点

(1)增加新构件时很难对容器中的构建类型进行限制。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册