本文作者:小黑黑

[设计模式]行为型模式之迭代器模式

小黑黑 1年前 ( 2019-03-04 ) 941 抢沙发
[设计模式]行为型模式之迭代器模式摘要: 一、引言        迭代器模式又称为游标模式,是行为型设计模式中的一种。迭代器是针对集对象而生的...

一、引言

        迭代器模式又称为游标模式,是行为型设计模式中的一种。迭代器是针对集对象而生的,对于对象而言,必然涉及到集合元素的添加和删除操作,同时可肯定支持遍历集合元素的操作,如果我们将遍历元素的方法封装到容器中,那么对于容器类来说就承担了过多的职责,容器类不仅要维护自身内部的数据而且还要对外提供遍历的接口方法。如果我们不提供遍历方法而让使用者自己去实现,又会让容器的内部结构暴露无遗,所以迭代器模式应运而生,在客户访问类与容器之间放置一个迭代器。

二、动机

        在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。

三、意图

        提供一种方法顺序的访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。                 --《设计模式》 GoF

四、结构图

123.PNG

4.1  模式的组成

        1、抽象迭代器角色(Iterator):负责定义访问和遍历元素的接口。

        2、具体迭代器角色(ConcreteIterator):实现了迭代器接口,并需要记录遍历中的游标当前位置。

        3、抽象聚合角色(Aggregate):负责定义获得迭代器角色的接口,声明一个方法用于创建一个迭代器对象。

        4、具体聚合角色(ConcreteAggregate):实现聚合角色接口,实现抽象聚合角色中创建迭代器角色的方法,并返回一个与该具体聚合相对应的具体的迭代器实例。

五、迭代器模式的具体实现

        下面我们将以肯德基的菜单为例,使用代码实现迭代器模式:

    /// <summary>
    /// 迭代器接口类
    /// </summary>
    public interface IIterator<T>
    {
        /// <summary>
        /// 当前对象
        /// </summary>
        T Current { get; }

        /// <summary>
        /// 获取是否还有下一个元素
        /// </summary>
        bool MoveNext();

        /// <summary>
        /// 重置游标位置
        /// </summary>
        void Reset();
    }
    
    /// <summary>
    /// 肯德基菜单迭代器,相当于具体迭代器类
    /// </summary>
    public class KFCMenuIterator : IIterator<Food>
    {
        private Food[] foodArray = null;

        public KFCMenuIterator(KFCMenu kfc)
        {
            foodArray = kfc.GetFoodList();
        }

        private int nextIndex = -1;

        /// <summary>
        /// 获取当前对象
        /// </summary>
        public Food Current
        {
            get { return foodArray[nextIndex]; }
        }

        /// <summary>
        /// 获取是否还有下一个元素
        /// </summary>
        public bool MoveNext()
        {
            return foodArray.Length > ++nextIndex;
        }

        /// <summary>
        /// 重置游标位置
        /// </summary>
        public void Reset()
        {
            nextIndex = -1;
        }
    }
    
    /// <summary>
    /// 麦当劳菜单迭代器,相当于具体迭代器类
    /// </summary>
    public class McDonaldMenuIterator : IIterator<Food>
    {
        private List<Food> foodList = null;

        public McDonaldMenuIterator(McDonaldMenu mcdonald)
        {
            foodList = mcdonald.GetFoodList();
        }

        private int nextIndex = -1;

        /// <summary>
        /// 获取当前对象
        /// </summary>
        public Food Current
        {
            get { return foodList[nextIndex]; }
        }

        /// <summary>
        /// 获取是否还有下一个元素
        /// </summary>
        public bool MoveNext()
        {
            return foodList.Count > ++nextIndex;
        }

        /// <summary>
        /// 重置游标位置
        /// </summary>
        public void Reset()
        {
            nextIndex = -1;
        }
    }
    
    /// <summary>
    /// 食物抽象聚合类,相当于抽象Aggregate
    /// </summary>
    public interface IFoodAggregate<T>
    {
        /// <summary>
        /// 获取一个迭代器对象
        /// </summary>
        IIterator<T> GetIterator();
    }
    
    /// <summary>
    /// KFC菜单类
    /// </summary>
    public class KFCMenu : IFoodAggregate<Food>
    {
        private Food[] foodArray = null;

        public KFCMenu(Food[] foodArray)
        {
            this.foodArray = foodArray;
        }

        /// <summary>
        /// 获取食物列表
        /// </summary>
        public Food[] GetFoodList()
        {
            return this.foodArray;
        }

        /// <summary>
        /// 获取迭代器对象
        /// </summary>
        /// <returns></returns>
        public IIterator<Food> GetIterator()
        {
            return new KFCMenuIterator(this);
        }
    }
    
    /// <summary>
    /// 麦当劳菜单类
    /// </summary>
    public class McDonaldMenu : IFoodAggregate<Food>
    {
        private List<Food> foodList = null;

        public McDonaldMenu(List<Food> foodList)
        {
            this.foodList = foodList;
        }

        /// <summary>
        /// 获取食物列表
        /// </summary>
        public List<Food> GetFoodList()
        {
            return this.foodList;
        }

        /// <summary>
        /// 获取迭代器对象
        /// </summary>
        /// <returns></returns>
        public IIterator<Food> GetIterator()
        {
            return new McDonaldMenuIterator(this);
        }
    }
    
    /// <summary>
    /// 实物类
    /// </summary>
    public class Food
    {

        public int Id { get; set; }

        public string Name { get; set; }

        public decimal Price { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {

            {
                Console.WriteLine("KFC菜单");

                Food[] kfcFood = new Food[]
                {
                new Food()
                {
                    Id = 1,
                    Name = "汉堡",
                    Price = 11M
                },
                new Food()
                {
                    Id = 2,
                    Name = "鸡翅",
                    Price = 5M
                },
                new Food()
                {
                    Id = 3,
                    Name = "可乐",
                    Price = 8M
                }
                };

                IFoodAggregate<Food> kfcAggregate = new KFCMenu(kfcFood);
                IIterator<Food> itreator = kfcAggregate.GetIterator();

                while (itreator.MoveNext())
                {
                    Food food = itreator.Current;
                    Console.WriteLine($"{food.Id}, {food.Name}, {food.Price}");
                }

            }

            {
                Console.WriteLine("McDonald菜单");

                List<Food> foodList = new List<Food>
                {
                    new Food()
                    {
                        Id = 1,
                        Name = "汉堡",
                        Price = 11M
                    },
                    new Food()
                    {
                        Id = 2,
                        Name = "鸡米花",
                        Price = 5M
                    },
                    new Food()
                    {
                        Id = 3,
                        Name = "咖啡",
                        Price = 8M
                    }
                };

                IFoodAggregate<Food> mcdonaldAggregate = new McDonaldMenu(foodList);
                IIterator<Food> itreator = mcdonaldAggregate.GetIterator();

                while (itreator.MoveNext())
                {
                    Food food = itreator.Current;
                    Console.WriteLine($"{food.Id}, {food.Name}, {food.Price}");
                }

            }

            Console.Read();
        }
    }

        我们可以看到肯德基和麦当劳的菜单有所不同,肯德基使用数组存放的,而麦当劳是用集合存放的,但通过迭代器方式,上端人员不用关心到底是哪种数据集合,可以使用通用的方式去遍历对象。这就是迭代器模式的好处。

六、迭代器模式的优缺点

优点:

        1、迭代器模式使用访问一个聚合对象的内容而无需暴露它的内部表示。

        2、迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。

缺点:

        1、迭代器模式在遍历的时候不能更改迭代器所在的集合结构,所以使用foreach语句只能对集合进行遍历,不能再遍历的同时修改集合中的元素的内容。

分享到: 网站分享代码

发表评论

快捷回复:

评论列表 (暂无评论,941人围观)参与讨论

还没有评论,来说两句吧...