找回密码
 立即注册
首页 业界区 业界 设计模式(十六)迭代器

设计模式(十六)迭代器

姊囝 2025-6-9 08:27:42
一、定义

提供一种方法顺序访问一个聚合对象中的各个元素,且不用暴露该对象的内部表示。迭代器模式是一种对象行为型模式,又称为游标(Cursor)模式。
二、描述

在软件系统中,聚合对象拥有两个职责:一是存储数据,二是遍历数据。从依赖性来看,前者是聚合对象的基本职责,而后者既是可变化的,又是可分离的。因此,可以将遍历数据的行为从聚合对象中分离出来,封装在迭代器对象中,由迭代器来提供遍历聚合对象内部数据的行为,这将简化聚合对象的设计,更加符合单一职责原则的要求。包含以下四个角色:
1.png
1、Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法。
2、ConcreteIterator(具体迭代器):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。
3、Aggregate(抽象聚合类):它用于存储和管理元素对象,声明一个CreateIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
4、ConcreteAggregate(具体聚合类):它是抽象聚合类的子类,实现了在抽象聚合类中声明的CreateIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。
三、例子

X公司为某商场开发了一套销售管理系统,在对该系统进行分析和设计时,M公司开发人员发现经常需要对系统中的商品数据、客户数据等进行遍历,为了复用这些遍历代码,开发人员设计了一个抽象的数据聚合类AbstractObjectList,而将存储商品和客户登记的类作为其子类。
2.png

AbstractObjectList:抽象聚合类
  1. public abstract class AbstractObjectList
  2. {
  3.     protected IList<object> objectList = new List<object>();
  4.     public AbstractObjectList (IList<object> objectList)
  5.     {
  6.         this.objectList = objectList;
  7.     }
  8.     public void AddObject(object obj)
  9.     {
  10.         this.objectList.Add(obj);
  11.     }
  12.     public void RemoveObject(object obj)
  13.     {
  14.         this.objectList.Remove(obj);
  15.     }
  16.     public IList<Object> GetObjectList()
  17.     {
  18.         return this.objectList;
  19.     }
  20.     // 声明创建迭代器对象的抽象工厂方法
  21.     public abstract AbstractIterator CreateIterator();
  22. }
复制代码
ProductList、ProductIterator:具体聚合类、具体迭代器,具体迭代器是具体聚合类的内部类
  1. public class ProductList : AbstractObjectList
  2. {
  3.     public ProductList(IList<object> objectList) : base(objectList)
  4.     {
  5.     }
  6.     public override AbstractIterator CreateIterator()
  7.     {
  8.         return new ProductIterator(this);
  9.     }
  10.     private class ProductIterator : AbstractIterator
  11.     {
  12.         private ProductList productList;
  13.         private IList<object> products;
  14.         private int cursor1;    // 定义一个游标,用于记录正向遍历的位置
  15.         private int cursor2;    // 定义一个游标,用于记录逆向遍历的位置
  16.         public ProductIterator(ProductList productList)
  17.         {
  18.             this.productList = productList;
  19.             this.products = productList.GetObjectList();       // 获取集合对象
  20.             this.cursor1 = 0;                                  // 设置正向遍历游标的初始值
  21.             this.cursor2 = this.products.Count - 1;            // 设置逆向遍历游标的初始值
  22.         }
  23.         public object GetNextItem()
  24.         {
  25.             return products[cursor1];
  26.         }
  27.         public object GetPreviousItem()
  28.         {
  29.             return products[cursor2];
  30.         }
  31.         public bool IsFirst()
  32.         {
  33.             return cursor2 == -1;
  34.         }
  35.         public bool IsLast()
  36.         {
  37.             return cursor1 == products.Count;
  38.         }
  39.         public void Next()
  40.         {
  41.             if (cursor1 < products.Count)
  42.             {
  43.                 cursor1++;
  44.             }
  45.         }
  46.         public void Previous()
  47.         {
  48.             if (cursor2 > -1)
  49.             {
  50.                 cursor2--;
  51.             }
  52.         }
  53.     }
  54. }
复制代码
AbstractIterator:抽象迭代器
  1. public interface AbstractIterator
  2. {
  3.     void Next();               // 移动至下一个元素
  4.     bool IsLast();             // 判断是否为最后一个元素
  5.     void Previous();           // 移动至上一个元素
  6.     bool IsFirst();            // 判断是否为第一个元素
  7.     object GetNextItem();      // 获取下一个元素
  8.     object GetPreviousItem();  // 获取上一个元素
  9. }
复制代码
Program:客户端测试类
  1. IList<object> products = new List<object>();
  2. products.Add("倚天剑");
  3. products.Add("屠龙刀");
  4. products.Add("断肠草");
  5. products.Add("葵花宝典");
  6. products.Add("四十二章经");
  7. AbstractObjectList objectList = new ProductList(products);      // 创建聚合对象
  8. AbstractIterator iterator = objectList.CreateIterator();        // 创建迭代器对象
  9. Console.WriteLine("正向遍历");
  10. while (!iterator.IsLast())
  11. {
  12.     Console.Write(iterator.GetNextItem() + ",");
  13.     iterator.Next();
  14. }
  15. Console.WriteLine();
  16. Console.WriteLine("-------------------------------------------------------");
  17. Console.WriteLine("逆向遍历");
  18. while (!iterator.IsFirst())
  19. {
  20.     Console.Write(iterator.GetPreviousItem() + ",");
  21.     iterator.Previous();
  22. }
  23. Console.ReadLine();
复制代码
3.png

四、总结

1、优点

(1)迭代器模式支持以不同方式遍历一个聚合对象,在同一个聚合对象上可以定义多种便利方式。在迭代器模式中,只需用一个不同的迭代器来替换原有迭代器即可改变遍历算法,也可以自己定义迭代器的子类以支持新的遍历方法。
(2)迭代器模式简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
(3)在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,符合开闭原则。
2、缺点

(1)由于迭代器模式将存储数据和遍历数据的职责分离,在增加新的聚合类需要对应增加新的迭代器类,类的个数会成对增加,这在一定程度上增加了系统的复杂性。
(2)抽象迭代器的设计难度较大,需要充分考虑系统将来的扩展。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是一件很容易的事情。

迭代器模式在.Net中,可以通过实现IEnumberable接口即可,不再需要单独实现,迭代器模式中的聚集接口和迭代器接口都已经存在了,其中IEnumerator接口扮演的就是迭代器角色,IEnumberable接口则扮演的就是抽象聚集的角色,其中定义了GetEnumerator()方法。


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