设计模式之迭代器

简介: 设计模式之迭代器

迭代器模式介绍



迭代器模式是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈、树等)的情况下遍历集合中所有的元素。


迭代器模式满足了单一职责和开闭原则,外界的调用方也不需要知道任何一个不同的数据结构在使用上的遍历差异。


迭代器模式的主要思想是将集合的遍历行为抽取为单独的迭代器对象。



除实现自身算法外,迭代器还封装了遍历操作的所有细节,比如当前位置和末尾剩余元素的数量、同时还有提供一个获取集合元素的基本方法。客户端可不断调用该方法直到它不返回任何内容(已遍历所有元素)、所有迭代器必须实现相同的接口(只要有合适的迭代器,客户端代码就能兼容任何类型的集合或遍历算法)。


迭代器的结构


  • 迭代器接口: 声明了遍历集合所需的操作。(获取下一个元素,获取当前位置和重新开始迭代等)


  • 具体迭代者:实现遍历集合的一种特定算法。(迭代器必须跟踪自身遍历的进度)


  • 集合接口:声明一个或多个方法来获取与集合兼容的迭代器。(返回方法的类型必须被声明为迭代器接口,因此具体集合可以返回各种不同种类的迭代器)


  • 具体集合:会在客户端请求迭代器时返回一个特定的具体迭代器类。


  • 客户端:通过集合和迭代器的接口与两者进行交互。这样一来客户端无需与具体类进行耦合,允许同一客户端代码使用各种不同的集合和迭代器。


应用场景


  • 当集合背后为复杂的数据结构,且你希望对客户端隐藏其复杂性时。


  • 想避免程序中重复的遍历代码


  • 程序代码能够遍历不同的甚至是无法预知的数据结构时。


实现方式


1、声明迭代器接口


2、声明集合接口并描述一个获取迭代器的方法,其返回值必须是迭代器接口。


3、为希望使用迭代器遍历的集合实现具体的迭代器类。


4、在你的集合类中实现集合接口。


5、在客户端使用迭代器替代所有集合遍历代码。


Demo


在迭代器的帮助下,客户端可以用一个迭代器接口以相似的方式遍历不同集合中的元素。


迭代器模式的辨别


  • 迭代器可以通过导航方法(next和previous)来轻松识别。


  • 使用迭代器的客户端代码可能没有其所遍历的集合的直接访问权限(二者是完全分离的)。



下面罗列了一个对人员集合进行排序的迭代器模式。


人员迭代器


   /// <summary>
    /// 人员迭代器
    /// 继承接口IEnumerator,显示实现了Current、MoveNext、Reset方法。
    /// </summary>
    abstract class PeopleIterator:IEnumerator  
    {        
         public abstract int Key();
        public abstract object Current();
        public abstract bool MoveNext();  
        public abstract void Reset();
        object IEnumerator.Current
        {
            get { return Current(); }
        }
    }


抽象集合迭代器和其实现

 /// <summary>
    /// 抽象的集合迭代器
    /// </summary>
    public abstract class AggregateIterator :IEnumerable
    {
        /// <summary>
        /// 得到内部的集合
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerator GetEnumerator();
    }
    /// <summary>
    /// 集合的迭代器类
    /// 具体排序的逻辑在这里写着
    /// </summary>
    class AlphabeticalOrderIterator : PeopleIterator
    {
        private PeopleCollection _collection;
        private int _position = -1;
        private bool _reverse = false;
        public AlphabeticalOrderIterator(PeopleCollection collection,bool reverse=false)
        {
            this._collection = collection;
            _reverse = reverse;
            if (reverse)
            {
                _position = collection.getItems().Count;
            }            
        }
        /// <summary>
        /// 当前的值
        /// </summary>
        /// <returns></returns>
        public override object Current()
        {
            return this._collection.getItems()[_position];           
        }
        /// <summary>
        /// 此时的索引
        /// </summary>
        /// <returns></returns>
        public override int Key()
        {
            return this._position;
        }
        /// <summary>
        /// 下一个  位置position进行调整
        /// </summary>
        /// <returns></returns>
        public override bool MoveNext()
        {
            int updatedPosition = this._position + (this._reverse ? -1 : 1);
            if (updatedPosition >= 0 && updatedPosition < this._collection.getItems().Count)
            {
                this._position = updatedPosition;
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 重置
        /// </summary>
        public override void Reset()
        {
            this._position = this._reverse ? this._collection.getItems().Count - 1 : 0;
        }
    }


具体的人员集合和其Main()方法验证


 /// <summary>
    /// 具体的人员集合
    /// </summary>
    public class PeopleCollection :AggregateIterator
    {
        List<string> _collection = new List<string>();
        bool _direction = false;
        public void ReverseDirection() 
        {
            _direction = !_direction;
        }
        public List<string> getItems() 
        {
            return _collection;
        }
        public void AddItem(string item) 
        {
            _collection.Add(item);
        }
        public override IEnumerator GetEnumerator()
        {
            return new AlphabeticalOrderIterator(this,_direction);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var collection = new PeopleCollection();
            collection.AddItem("阿五");
            collection.AddItem("阿六");
            collection.AddItem("阿七");
            Console.WriteLine("遍历下");
            foreach (var item in collection)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("倒序");
            collection.ReverseDirection();
            foreach (var item in collection)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }
    }


输出结果


迭代器模式在理解上还是有一点难度的,因为平时在使用集合时各个语言都已经将集合的各种操作方法都已经罗列出来了,调用人员直观调用即可。所以我们在了解其设计模式思想时,还是要多进行实践和思考。


有些东西看的多了,做的多了,自然而然就明白了。



目录
相关文章
|
设计模式 Java
浅析Java设计模式【3.8】——迭代器
Java常用设计模式,迭代器模式
104 0
浅析Java设计模式【3.8】——迭代器
|
设计模式 Java 数据安全/隐私保护
设计模式是什么鬼(迭代器)
设计模式是什么鬼(迭代器)
设计模式是什么鬼(迭代器)
|
Python 设计模式
python设计模式(十七):迭代器模式——迭代器与生成器
迭代模式:对外提供一个接口,实现顺序访问聚合数据,但是不显示该数据的内部机制。这就是Python中大名鼎鼎的迭代器。 实现迭代模式对于Python来说没有多余的代码,寥寥几行代码足可以实现迭代模式。 示例code: # -*- coding:utf-8 -*-def FibonacciSeque...
1391 0
|
Java C# 设计模式
使用C# (.NET Core) 实现迭代器设计模式 (Iterator Pattern)
本文的概念来自深入浅出设计模式一书 项目需求 有两个饭店合并了, 它们各自有自己的菜单. 饭店合并之后要保留这两份菜单. 这两个菜单是这样的: 菜单项MenuItem的代码是这样的: 最初我们是这样设计的, 这是第一份菜单: 这是第2份菜单: 同时有两个菜单存在的问题 问题就是多个菜单把事情变复杂了.
1032 0
|
Java 设计模式
内部类+迭代器设计模式的java实现。。。
interface Iterator{   void next() ;   Object current() ;   boolean end() ; } class Sequence {   Integer []buf  ;  int length =0 ;  Sequen...
693 0
|
算法 C++ 容器
设计模式之iterator模式到STL中iterator迭代器
设计模式之iterator模式到STL中iterator迭代器 近日看《设计模式:可复用面向对象软件的基础》一书中23种模式中就有iterator迭代模式,且篇幅颇大。
1241 0
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式