问题:
在面向对象的软件设计中,经常会遇到一些聚集对象,按一定的顺序的遍历访问问题,这个遍历算法究竟应该由谁来实现呢,聚集对象本身?这样聚集对象承受了过多的功能,不仅要维护聚集对象内的元素,还要提供遍历自身的接口,而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历,这不符合单一职责原则。如果将遍历算法交给客户端,会将容器的内部细节暴露无遗,而且客户端与聚集对象高度耦合。分离了集合对象的遍历行为,将遍历算法交给这个迭代器角色来完成,可以很好的避免容器内部细节的暴露,而且也使得设计符合“单一职责原则”,另外迭代器模式抽象了具体迭代器角色,可以通过对一个抽象迭代器多个集成可来完成同一聚集对象的多种遍历。

定义:
迭代器(Iterator)模式,又叫做游标(Cursor)模式。
提供一种方法顺序访问一个聚合对象(或容器对象:container)中各个元素, 而又不需暴露该对象的内部表示。

意图:
分离了集合对象的遍历行为,将遍历算法交给这个迭代器角色来完成,可以很好的避免容器内部细节的暴露,而且也使得设计符合“单一职责原则”,另外迭代器模式抽象了具体迭代器角色,可以通过对一个抽象迭代器多个集成可来完成同一聚集对象的多种遍历。

参与者:
•迭代器角色(Iterator):
定义访问和遍历元素的接口。
•具体迭代器角色(Concrete Iterator):
关联到被迭代的具体聚集对象角色,继承迭代器角色实现具体的迭代,并负责管理记录遍历中的当前位置。
•聚集对象抽象角色(Aggregate):
责提供创建具体迭代器角色的接口。
•具体聚集对象角色(Concrete Aggreate):
持有一个对象的集合,实现创建具体迭代器角色的接口,返回集合遍历所依赖的一个迭代器。
UML图:


实例说明:

诺基亚手机工厂
诺基亚返修仓库遍历返修手机

uml图如下:

代码:

/// <summary>
/// 返修手机对象
/// </summary>
public class ReworkPhone
{
    /// <summary>
    /// 手机名称
    /// </summary>
    public string PhoneName { get; set; }
    /// <summary>
    /// 生产日期
    /// </summary>
    public string ProductionDate { get; set; }

/// <summary>
    /// 返厂日期
    /// </summary>
    public string ReworkDate { get; set; }
}
/// <summary>
/// 聚集对象抽象角色(Aggregate)供创建具体迭代器角色的接口。
/// </summary>
public interface IReworkPhoneContainer
{
    IReworkIterator GetIterator();
}
/// <summary>
/// 定义访问和遍历元素的接口
/// </summary>
public interface IReworkIterator
{
    bool HasNext();
    void First();
    void Next();
    Object CurrentItem();
}
/// <summary>
/// 返修手机仓库(具体聚集对象角色)
/// </summary>
public class ReworkPhoneContainer : IReworkPhoneContainer
{
    List<ReworkPhone> ReworkPhoneList = null;
    public ReworkPhoneContainer()
    {
        ReworkPhoneList = new List<ReworkPhone>();
    }
    public IReworkIterator GetIterator()
    {
        return new ReworkConcreteIterator(this);
    }
    public void Add(ReworkPhone phone)
    {
        ReworkPhoneList.Add(phone);
    }
    public object GetItemByIndex(int index)
    {
        return ReworkPhoneList[index];
    }
    public int Count
    {
        get { return ReworkPhoneList.Count; }
    }
}
/// <summary>
/// 返修仓库 中返修手机迭代的具体实现 (具体迭代器角色)以怎样的方式顺序遍历元素
/// </summary>
public class ReworkConcreteIterator : IReworkIterator
{
    private ReworkPhoneContainer list;

private int index;

public ReworkConcreteIterator(ReworkPhoneContainer list)
    {
        this.list = list;

index = 0;
    }
    public bool HasNext()
    {
        return index < list.Count;
    }

public void First()
    {
        index = 0;
    }

public void Next()
    {
        if (index < list.Count)
        {
            index++;
        }
    }

public object CurrentItem()
    {
        return list.GetItemByIndex(index);
    }
}
void IteratorTest()
{
    ReworkPhoneContainer PhoneContainer = new ReworkPhoneContainer();

PhoneContainer.Add(new ReworkPhone() { PhoneName = "N8", ProductionDate = "2011-6-27 6:00:46", ReworkDate = "2012-1-27 6:40:01" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N9", ProductionDate = "2011-1-27 9:44:46", ReworkDate = "2012-2-27 8:45:09" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N9", ProductionDate = "2011-4-27 14:44:46", ReworkDate = "2012-3-27 14:05:00" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N8", ProductionDate = "2012-7-27 16:44:46", ReworkDate = "2012-4-27 16:45:01" });

IReworkIterator iterator = new ReworkConcreteIterator(PhoneContainer);
    while (iterator.HasNext())
    {
        ReworkPhone item = iterator.CurrentItem() as ReworkPhone;
        System.Console.WriteLine("{0}送修的{1},返修完成!", item.ReworkDate, item.PhoneName);
        iterator.Next();
    }
    System.Console.WriteLine("所有手机返修完成!");
    System.Console.Read();
}

.NET中的Iterator模式

.NET下已提供了一个迭代器的角色(IEnumerator)与聚集接口(IEnumerable),并在.Net集合类中有大量Iterator模式的实现

/// <summary>
/// 返修手机对象
/// </summary>
public class ReworkPhone
{
    /// <summary>
    /// 手机名称
    /// </summary>
    public string PhoneName { get; set; }
    /// <summary>
    /// 生产日期
    /// </summary>
    public string ProductionDate { get; set; }

/// <summary>
    /// 返厂日期
    /// </summary>
    public string ReworkDate { get; set; }
}

/// <summary>
/// 返修手机仓库(具体聚集对象角色)
/// </summary>
public class ReworkPhoneContainer : IEnumerable
{
    List<ReworkPhone> ReworkPhoneList = null;
    public ReworkPhoneContainer()
    {
        ReworkPhoneList = new List<ReworkPhone>();
    }
    public void Add(ReworkPhone phone)
    {
        ReworkPhoneList.Add(phone);
    }
    public object GetItemByIndex(int index)
    {
        return ReworkPhoneList[index];
    }
    public int Count
    {
        get { return ReworkPhoneList.Count; }
    }

public IEnumerator GetEnumerator()
    {
        return new ReworkConcreteIterator(this);
    }
}
/// <summary>
/// 返修仓库 中返修手机迭代的具体实现 (具体迭代器角色)以怎样的方式顺序遍历元素
/// </summary>
public class ReworkConcreteIterator : IEnumerator
{
    private ReworkPhoneContainer list;

private int index;

public ReworkConcreteIterator(ReworkPhoneContainer list)
    {
        this.list = list;
        index = 0;
    }

public void Reset()
    {
        index = 0;
    }
    public bool MoveNext()
    {
        if (index < list.Count-1)
        {
            index++;
            return true;
        }
        return false;
    }

public object Current
    {
        get
        {
            return list.GetItemByIndex(index);
        }
    }
}
/// <summary>
/// 客户端测试
/// </summary>
public void IteratorTest()
{
    ReworkPhoneContainer PhoneContainer = new ReworkPhoneContainer();

PhoneContainer.Add(new ReworkPhone() { PhoneName = "N8", ProductionDate = "2011-6-27 6:00:46", ReworkDate = "2012-1-27 6:40:01" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N9", ProductionDate = "2011-1-27 9:44:46", ReworkDate = "2012-2-27 8:45:09" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N9", ProductionDate = "2011-4-27 14:44:46", ReworkDate = "2012-3-27 14:05:00" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N8", ProductionDate = "2012-7-27 16:44:46", ReworkDate = "2012-4-27 16:45:01" });

IEnumerator iterator = new ReworkConcreteIterator(PhoneContainer);
    do
    {
        ReworkPhone item = iterator.Current as ReworkPhone;
        System.Console.WriteLine("{0}送修的{1},返修完成!", item.ReworkDate, item.PhoneName);
    }
    while (iterator.MoveNext());

System.Console.WriteLine("所有手机返修完成!");
    System.Console.Read();
}

.NET2.0 下提供了yield return,可以在实现利聚集接口(IEnumerable)接口 IEnumerator GetEnumerator() 方法上 实现一个简单的迭代

/// <summary>
/// 返修手机对象
/// </summary>
public class ReworkPhone
{
    /// <summary>
    /// 手机名称
    /// </summary>
    public string PhoneName { get; set; }
    /// <summary>
    /// 生产日期
    /// </summary>
    public string ProductionDate { get; set; }

/// <summary>
    /// 返厂日期
    /// </summary>
    public string ReworkDate { get; set; }
}

/// <summary>
/// 返修手机仓库(具体聚集对象角色)
/// </summary>
public class ReworkPhoneContainer : IEnumerable
{
    List<ReworkPhone> ReworkPhoneList = null;
    public ReworkPhoneContainer()
    {
        ReworkPhoneList = new List<ReworkPhone>();
    }
    public void Add(ReworkPhone phone)
    {
        ReworkPhoneList.Add(phone);
    }
    public object GetItemByIndex(int index)
    {
        return ReworkPhoneList[index];
    }
    public int Count
    {
        get { return ReworkPhoneList.Count; }
    }

public IEnumerator GetEnumerator()
    {
        foreach (var item in ReworkPhoneList)
        {
            yield return item;
        } 
    }
}
/// <summary>
/// 客户端测试
/// </summary>
public void IteratorTest()
{
    ReworkPhoneContainer PhoneContainer = new ReworkPhoneContainer();

PhoneContainer.Add(new ReworkPhone() { PhoneName = "N8", ProductionDate = "2011-6-27 6:00:46", ReworkDate = "2012-1-27 6:40:01" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N9", ProductionDate = "2011-1-27 9:44:46", ReworkDate = "2012-2-27 8:45:09" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N9", ProductionDate = "2011-4-27 14:44:46", ReworkDate = "2012-3-27 14:05:00" });
    PhoneContainer.Add(new ReworkPhone() { PhoneName = "N8", ProductionDate = "2012-7-27 16:44:46", ReworkDate = "2012-4-27 16:45:01" });

foreach (var obj in PhoneContainer)
    {
        ReworkPhone item = obj as ReworkPhone;
        System.Console.WriteLine("{0}送修的{1},返修完成!", item.ReworkDate, item.PhoneName);
    }
    System.Console.WriteLine("所有手机返修完成!");
    System.Console.Read();
}

优点:
•支持以不同的方式遍历一个集合对象。根据实现方式的不同,效果上会有差别。
•简化了集合对象的接口。聚集对象不负责提供遍历算法。
•对同一个容器对象,可以同时进行多个遍历。因为遍历状态是保存在每一个迭代器对象中的。

缺点:

•增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。。
•集合类与迭代器类非常紧密地关联在一起。

应用情景:
•访问一个容器对象的内容而无需暴露它的内部表示。
•支持对容器对象的多种遍历。
•为遍历不同的容器结构提供一个统一的接口。

转http://www.cnblogs.com/ejiyuan/archive/2012/06/27/2566190.html

转载于:https://www.cnblogs.com/boke/archive/2012/08/15/2639426.html

设计模式学习总结-迭代器模式(Iterator Pattern)相关推荐

  1. 设计模式 - 迭代器模式(iterator pattern) 具体解释

    迭代器模式(iterator pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 迭代器模式(iterator pattern) : 提供一 ...

  2. 设计模式:迭代器模式(Iterator Pattern)

    迭代器模式(Iterator Pattern): 属于行为型模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即: 不暴露其内部结构.

  3. 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)

    设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用 ...

  4. 设计模式 - 学习笔记 - 工厂模式Factory Pattern

    设计模式 - 学习笔记 - 工厂模式Factory Pattern 1. 简单工厂 1.1 应用场景 1.2 UML 1.3 优劣分析 好处 缺点 1.4 代码示例 抽象产品 AbstractProd ...

  5. 解读设计模式----迭代器模式(Iterator Pattern),谁才是迭代高手

    一.你在开发中使用过迭代吗?      当你在使用JavaScript开发客户端应用的时候使用过for...in吗?  1<script type="text/javascript&q ...

  6. 迭代器模式(Iterator pattern)

    一. 引言 迭代这个名词对于熟悉Java的人来说绝对不陌生.我们常常使用JDK提供的迭代接口进行java collection的遍历: Iterator it = list.iterator(); w ...

  7. 【java设计模式】【行为模式Behavioral Pattern】迭代器模式Iterator Pattern

    1 package com.tn.pattern; 2 3 public class Client { 4 public static void main(String[] args) { 5 Obj ...

  8. 听webcast的行为型模式篇-迭代器模式(Iterator Pattern) 记录

    < DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd> dotnet或java里 ...

  9. 33迭代器模式(Iterator Pattern)

    动机(Motivate):     在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种" ...

最新文章

  1. 只需1秒,无人机就能平地翻跟头 | IEEE
  2. 进度条设置_项目功能分解4:MATLAB GUI如何设计有特色的进度条。
  3. GitPages个人域名博客
  4. php的静态变量static在函数内部
  5. [go]---从java到go(02)---一个简单的handler模式的实现
  6. hadoop重启后 9000端口不在
  7. 图像缩放--OpenCV cvResize函数
  8. 网管学习日记-ospf认证
  9. 【AAAI 2021】全部接受论文列表(一)
  10. [BJDCTF 2nd] 燕言燕语-y1ng
  11. 关于α测试与β测试的区别
  12. 被删除的pip,重新安装
  13. 串口通信——串口uart
  14. mysql5.7增加ssl认证(1)
  15. C++ STL函数 map (henu.hjy)
  16. 【leetcode24-----1比特与2比特字符】
  17. 笛卡儿积、自然连接、等值连接的区别
  18. 数说故事车企数字化转型案例——科学分配预算评估社媒营销效果
  19. 一名数据分析师的SQL学习历程
  20. .c文件生成.cgi文件

热门文章

  1. puppet (三)
  2. COALESCE在SQL拼接中的大用途
  3. 《无线网络安全攻防实战》读书笔记
  4. ASP.NET Web API 过滤器创建、执行过程(二)
  5. DLR学习笔记(01)
  6. Numerical Geometry of Image
  7. 阿里云MVP北京闭门会圆满落幕 多把“利剑”助力开发者破阵蜕变
  8. sudo 密码超时时间
  9. 从PC、数据中心再到边缘计算,Zen架构的终点在哪?
  10. Docker+Jenkins持续集成环境(1)使用Docker搭建Jenkins+Docker持续集成环境