深入浅出设计模式——迭代器模式(Iterator Pattern)

模式动机

一个聚合对象,如一个列表(List)或者一个集合(Set),应该提供一种方法来让别人可以访问它的元素,而又不需要暴露它的内部结构。
针对不同的需要,可能还要以不同的方式遍历整个聚合对象,但是我们并不希望在聚合对象的抽象层接口中充斥着各种不同遍历的操作。
怎样遍历一个聚合对象,又不需要了解聚合对象的内部结构,还能够提供多种不同的遍历方式,这就是迭代器模式所要解决的问题。
在迭代器模式中,提供一个外部的迭代器来对聚合对象进行访问和遍历,迭代器定义了一个访问该聚合元素的接口,并且可以跟踪当前遍历的元素,了解哪些元素已经遍历过而哪些没有。
有了迭代器模式,我们会发现对一个复杂的聚合对象的操作会变得如此简单。

模式定义
迭代器模式(Iterator Pattern) :提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)。迭代器模式是一种对象行为型模式。
Iterator Pattern: Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
Frequency of use: high
UML图

模式结构
迭代器模式包含如下角色:
Iterator: 抽象迭代器
ConcreteIterator: 具体迭代器
Aggregate: 抽象聚合类
ConcreteAggregate: 具体聚合类

模式分析
聚合是一个管理和组织数据对象的数据结构。
聚合对象主要拥有两个职责:一是存储内部数据;二是遍历内部数据。
存储数据是聚合对象最基本的职责。
将遍历聚合对象中数据的行为提取出来,封装到一个迭代器中,通过专门的迭代器来遍历聚合对象的内部数据,这就是迭代器模式的本质。迭代器模式是“单一职责原则”的完美体现。

在迭代器模式中应用了工厂方法模式,聚合类充当工厂类,而迭代器充当产品类,由于定义了抽象层,系统的扩展性很好,在客户端可以针对抽象聚合类和抽象迭代器进行编程。
由于很多编程语言的类库都已经实现了迭代器模式,因此在实际使用中我们很少自定义迭代器,只需要直接使用Java、C#等语言中已定义好的迭代器即可,迭代器已经成为我们操作聚合对象的基本工具之一。

模式实例与解析
想走?可以!先买票—迭代器模式示例
体系结构

Iterator: 抽象迭代器

namespace IteratorPattern
{
    //Iterator迭代器抽象类
    abstract class Iterator
    {
        //用于定义得到开始对象、得到下一个对象、
        //判断是否到结尾、当前对象等抽象方法,统一接口
        public abstract object First();
        public abstract object Next();
        public abstract bool IsDone();
        public abstract object CurrentItem();
    }
}

ConcreteIterator: 具体迭代器

using System;

namespace IteratorPattern
{
    //ConcreteIterator具体迭代器类,继承Iterator
    class ConcreteIterator : Iterator
    {
        //定义一个具体聚集对象
        private ConcreteAggregate aggregate;
        private int current = 0;        
        //初始化时将具体的聚集对象传入
        public ConcreteIterator(ConcreteAggregate aggregate)
        {
            this.aggregate = aggregate;
        }
        public override object First()
        {
            return aggregate[0];
        }
        public override object Next()
        {
            Object ret = null;
            current++;
            if (current < aggregate.Count)
            {
                ret = aggregate[current];
            }
            return ret;
        }
        public override bool IsDone()
        {
            return current >= aggregate.Count ? true : false;
        }
        public override object CurrentItem()
        {
            return aggregate[current];//返回当前的聚集对象
        }
    }
}

Aggregate: 抽象聚合类

namespace IteratorPattern
{
    //Aggregate聚集抽象类
    abstract class Aggregate
    {
        //创建迭代器
        public abstract Iterator CreateIterator();
    }
}

ConcreteAggregate: 具体聚合类

using System;
using System.Collections.Generic;

namespace IteratorPattern
{
    //ConcreteAggregate具体聚集类 继承Aggregate
    class ConcreteAggregate : Aggregate
    {
        //声明一个IList泛型变量,用于存放聚合对象,用ArrayList同样可以实现
        private IList<object> items = new List<Object>();
        public override Iterator CreateIterator()
        {
            return new ConcreteIterator(this);
        }
        public int Count
        {
            get { return items.Count; }//返回聚集总个数
        }
        //声明一个索引器
        public object this[int index]
        {
            get { return items[index]; }
            set { items.Insert(index, value); }
        }
    }
}

Client:客户类

using System;

namespace IteratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            ConcreteAggregate a = new ConcreteAggregate();
            a[0] = "张三";
            a[1] = "李四";
            a[2] = "王五";

            Iterator i = new ConcreteIterator(a);
            object item = i.First();
            while (!i.IsDone())
            {
                Console.WriteLine("{0} 请买车票!", i.CurrentItem());
                i.Next();//下一乘客
            }
            Console.Read();
        }
    }
}

模式优缺点
迭代器模式的优点
 它支持以不同的方式遍历一个聚合对象。
 迭代器简化了聚合类。
 在同一个聚合上可以有多个遍历。
 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。
迭代器模式的缺点
 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

模式适用环境
在以下情况下可以使用迭代器模式:
 访问一个聚合对象的内容而无须暴露它的内部表示。
 需要为聚合对象提供多种遍历方式。
 为遍历不同的聚合结构提供一个统一的接口。

【声明与感谢】
本文,站在许多巨人的肩膀上,借鉴和引用了许多他人拥有版权的作品或著述,在此,对前人们的贡献致谢。并同时公布引用的内容、原作者或来源(一些来源于互联网的内容本人无法追述本源,深表遗憾)。

【参考文献】
《设计模式—可复用面向对象软件的基础》作者: [美] Erich Gamma / Richard Helm / Ralph Johnson / John Vlissides 译者: 李英军 / 马晓星 / 蔡敏 / 刘建中 等 机械工业出版社
《重构—改善既有代码的设计》作者: Martin Fowler译者:候捷 中国电力出版社
《敏捷软件开发—原则、模式与实践》作者: Robert C. Martin 清华大学出版社
《程序员修炼之道—从小工到专家》作者: Andrew Hunt / David Thomas 电子工业出版社
《Head First 设计模式》作者: 弗里曼 译者: O'Reilly Taiwan公司 中国电力出版社
《设计模式之禅》 作者: 秦小波 机械工业出版社
MSDN WebCast 《C#面向对象设计模式纵横谈》 讲师:李建忠
刘伟. 设计模式. 北京:清华大学出版社, 2011.
刘伟. 设计模式实训教程. 北京:清华大学出版社, 2012.
《大话设计模式》 作者: 程杰 清华大学出版社
《C#图解教程》作者: 索利斯 译者: 苏林 / 朱晔 人民邮电出版社
《你必须知道的.NET》作者: 王涛
《项目中的.NET》作者: 李天平 电子工业出版社
《Microsoft .NET企业级应用架构设计》作者: (美)埃斯波西托等编著 译者: 陈黎夫
http://www.dofactory.com/Patterns/Patterns.aspx .NET Design Patterns
http://www.cnblogs.com/zhenyulu 博客作者:吕震宇
http://www.cnblogs.com/terrylee 博客作者:李会军
http://www.cnblogs.com/anlyren/ 博客作者:anlyren
http://www.cnblogs.com/idior 博客作者:idior
http://www.cnblogs.com/allenlooplee 博客作者:Allen lee
http://blog.csdn.net/ai92 博客作者:ai92
http://www.cnblogs.com/umlonline/ 博客作者:张传波
http://www.cnblogs.com/lovecherry/ 博客作者:LoveCherry

posted @ 2014-12-31 13:58  Bobby0322  阅读(993)  评论(0编辑  收藏  举报