【读书活动感悟分享】极客充电队——《Head First 设计模式》迭代器和组合模式读书心得_文章

【读书活动感悟分享】极客充电队——《Head First 设计模式》迭代器和组合模式读书心得

李兴礼
发表于 2025-11-10 09:49:46



1. 概述

1.1 迭代器模式

  • 定义:提供一种方法顺序访问聚合对象中的元素,而不暴露其内部表示。
  • 核心思想:将遍历逻辑与聚合对象解耦,统一访问接口。
  • 典型应用场景:集合类遍历、文件系统目录遍历、复杂对象结构的访问。

1.2 组合模式

  • 定义:将对象组合成树形结构以表示"部分-整体"的层次结构,使客户端可以统一处理单个对象和组合对象。
  • 核心思想:递归组合对象,形成树形结构。
  • 典型应用场景:文件系统目录结构、UI控件树、组织架构管理。

2. 模式组合使用场景

当需要遍历组合模式构建的树形结构时,迭代器模式能提供统一的访问方式。例如:

  • 遍历文件系统中的所有文件(包括子目录中的嵌套文件)
  • 计算UI控件树中所有子控件的布局
  • 统计组织架构中所有员工信息



3. 迭代器示例

  • 当两个不同数据结构实现的菜单进行打印时
  • 两种菜单需要循环打印两遍,当增加更多的菜单时需要不断的增加循环
  • 封装变化,上面的变化点在于每种数据类型的获取数据项的方法不一致接下来引入一个类(迭代器),他来封装遍历集合的方式,
  • 接口:
  • 迭代器类
  • 调用
  • 使用C#内置的迭代器类,使其可以被foreach进行遍历
  • 当引入其他的菜单,或者每次需要介绍不同的菜单时,对服务员类进行改造,完整的实现一个服务员类


  • 4. 基于上面的迭代器继续引入组合模式
  • 上面使用迭代器模式使服务员可以介绍多个菜单,现在菜单出现变动,需要加一份甜品子菜单,现在需要某种树形结构,可以容纳菜单、子菜单和菜单项
  • 单纯的迭代器模式无法满足目前的需求,此时引入组合模式,定义:允许你将对象组合成树形结构来表现部分-整体层次结构。组合让客户可以统一处理个别对象和对象组合。
  • 组合模式类图



  • 5. 实现示例:文件系统模拟



    5.1 类结构设计

  • // 组合模式基础接口
    public abstract class FileSystemComponent
    {
        public string Name { get; protected set; }
    
        protected FileSystemComponent(string name)
        {
            Name = name;
        }
    
        public abstract void Add(FileSystemComponent component);
        public abstract void Remove(FileSystemComponent component);
        public abstract IEnumerator GetEnumerator();
    }
    
    // 叶子节点:文件
    public class File : FileSystemComponent
    {
        public File(string name) : base(name) { }
    
        public override void Add(FileSystemComponent component) 
            => throw new InvalidOperationException("不能向文件中添加内容");
    
        public override void Remove(FileSystemComponent component) 
            => throw new InvalidOperationException("不能从文件中移除内容");
    
        public override IEnumerator GetEnumerator()
        {
            // 文件本身是叶子节点,返回自己
            yield return this;
        }
    }
    
    // 复合节点:目录
    public class Directory : FileSystemComponent
    {
        private List _children = new List();
    
        public Directory(string name) : base(name) { }
    
        public override void Add(FileSystemComponent component)
        {
            _children.Add(component);
        }
    
        public override void Remove(FileSystemComponent component)
        {
            _children.Remove(component);
        }
    
        public override IEnumerator GetEnumerator()
        {
            // 返回当前目录和所有子元素的迭代器
            foreach (var component in _children)
            {
                yield return component;
            }
        }
    }


  • 5.2 使用示例

  • class Program
    {
        static void Main()
        {
            // 构建文件系统结构
            var root = new Directory("根目录");
            
            var documents = new Directory("文档");
            documents.Add(new File("报告.docx"));
            documents.Add(new File("简历.pdf"));
    
            var pictures = new Directory("图片");
            var vacationPhotos = new Directory("度假照片");
            vacationPhotos.Add(new File("海滩.jpg"));
            vacationPhotos.Add(new File("山脉.png"));
            pictures.Add(vacationPhotos);
            pictures.Add(new File("logo.png"));
    
            root.Add(documents);
            root.Add(pictures);
            root.Add(new File("readme.txt"));
    
            // 使用迭代器遍历所有文件(递归遍历)
            TraverseComponents(root);
        }
    
        static void TraverseComponents(FileSystemComponent component)
        {
            foreach (var item in component)
            {
                if (item is Directory directory)
                {
                    Console.WriteLine($"目录: {item.Name}");
                    TraverseComponents(directory); // 递归遍历
                }
                else
                {
                    Console.WriteLine($"文件: {item.Name}");
                }
            }
        }
    }


  • 5.3 输出结果
  • 目录: 文档
    文件: 报告.docx
    文件: 简历.pdf
    目录: 图片
    目录: 度假照片
    文件: 海滩.jpg
    文件: 山脉.png
    文件: logo.png
    文件: readme.txt





















  • 51 0

    评论
    

    意见反馈