zoukankan      html  css  js  c++  java
  • 结构型模式之组合模式

    概述

    对于树形结构,当容器对象(如文件夹)的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象(可以是容器对象,也可以是叶子对象)并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理。由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下我们希望一致地处理它们,因为对于这些对象的区别对待将会使得程序非常复杂。组合模式为解决此类问题而诞生,它可以让叶子对象和容器对象的使用具有一致性

    定义

    组合模式(Composite Pattern):组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式。

    实现

    顶层基类

        public abstract class File
        {
            public string name { get; set; }
            public File(string name)
            {
                this.name = name;
            }
            /// <summary>
            /// 显示文件方法
            /// </summary>
            public virtual void Display()
            {
                Console.WriteLine(name);
            }
        }

    容器类

        public class Folder : File
        {
            /// <summary>
            /// 文件集合
            /// </summary>
            private List<File> files;
    
            public Folder(string name) : base(name)
            {
                files = new List<File>();
            }
            /// <summary>
            /// 新增文件方法
            /// </summary>
            /// <param name="file"></param>
            public void Add(File file)
            {
                files.Add(file);
            }
    
            public void Remove(File file)
            {
                files.Remove(file);
            }
    
            public override void Display()
            {
                base.Display();
                files.ForEach(p =>
                {
                    p.Display();
                });
            }
        }

    叶子节点类

        public class ImageFile : File
        {
            public ImageFile(string name) : base(name)
            { }
            public override void Display()
            {
                Console.WriteLine(base.name);
            }
        }
        public class TextFile : File
        {
            public TextFile(string name) : base(name)
            { }
            public override void Display()
            {
                Console.WriteLine(base.name);
            }
        }

    客户端

            static void Main(string[] args)
            {
                Folder folder = new Folder("总文件夹");
                folder.Add(new TextFile(string.Format("{0}日记文件.txt", GetLevelString(1))));
                folder.Add(new ImageFile(string.Format("{0}毕业照.JPG", GetLevelString(1))));
                Folder level_One_Folder = new Folder(string.Format("{0}1级文件夹", GetLevelString(1)));
                level_One_Folder.Add(new TextFile(string.Format("{0}盗墓笔记.txt", GetLevelString(2))));
                level_One_Folder.Add(new ImageFile(string.Format("{0}亵渎.txt", GetLevelString(2))));
                folder.Add(level_One_Folder);
                Folder level_Two_Folder = new Folder(string.Format("{0}2级文件夹", GetLevelString(2)));
                level_Two_Folder.Add(new TextFile(string.Format("{0}廊桥遗梦.txt", GetLevelString(3))));
                level_Two_Folder.Add(new ImageFile(string.Format("{0}陈乔恩.JPG", GetLevelString(3))));
                folder.Add(level_Two_Folder);
                folder.Display();
                Console.ReadLine();
            }
    
            static string GetLevelString(int level)
            {
                StringBuilder sb = new StringBuilder();
                for (var i = 0; i < level; i++)
                {
                    sb.Append("	");
                }
                return sb.ToString();
            }

    总结

    主要优点

    1、组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。

    2、 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。

    3、 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。

    4、 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

    主要缺点

          在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂

  • 相关阅读:
    html基础笔记
    webpack实用配置总结
    Vue生命周期
    Vue跨域解决方法
    日历
    绝对地址和相对地址
    HTML+CSS要点
    (利用DOM)在新打开的页面点击关闭当前浏览器窗口
    前端面试
    前端工程师的知识体系
  • 原文地址:https://www.cnblogs.com/Jabben_Yi/p/5560285.html
Copyright © 2011-2022 走看看