C#设计模式实现之迭代器模式

迭代器模式把对象的职责分离,职责分离可以最大限度减少彼此之间的耦合程度,从而建立一个松耦合的对象,这篇文章主要给大家介绍了关于C#设计模式实现之迭代器模式的相关资料,需要的朋友可以参考下

前言:

迭代器模式平时用的不多,因为不管C#还是Java都已经帮我封装了,但是你是否知道平时经常在用的东西本质是怎么回事呢。

看完迭代器模式你就知道C# foreach循环是怎么实现的了,我的另一篇C# Foreach循环本质与枚举器就讲解了foreach的本质,其中用到的就是迭代器模式。

按照惯例,例子走起。(写了几个小时浏览器崩溃,我看见在自动保存啊,结果没内容,再撸一遍精简点的吧)

一、餐馆合并菜单

现在有两个餐馆和并,其中一个餐馆做早餐,一个做晚餐。他们都有自己管理菜单的方式,现在两个餐馆合并需要对菜单进行统一管理,先让我来看看他们原来的样子。

两个菜单的菜单项都是一样的


    public class MenuItme
    {
        //名字
        public string Name { get; set; }
        //描述
        public string Description { get; set; }
        //是否素菜
        public bool Vegetarian { get; set; }
        //价格
        public double Price { get; set; }

        public MenuItme(string name, string description, bool vegetarian, double price) {
            Name = name;
            Description=description;
            Vegetarian = vegetarian;
            Price = price;
        }
    }

  早餐菜单,使用List管理,不限制长度


    public class BreakFastMenu
    {
        private List<MenuItme> menuItmes;
        public BreakFastMenu()
        {
            menuItmes = new List<MenuItme>();
            AddItem("梅菜扣肉饼", "好吃", false, 7);
            //菜单项...
        }

        public void AddItem(string name, string description, bool vegetarian, double price)
        {
            MenuItme menuItme = new MenuItme(name, description, vegetarian, price);
            menuItmes.Add(menuItme);
        }

        public List<MenuItme> GetMenuItmes()
        {
            return menuItmes;
        }
    }

  晚餐菜单,使用数组管理,限制长度为6


    public class DinerMenu
    {
        static readonly int Max_Items = 6;
        private int numberOfImtes = 0;
        private MenuItme[] menuItmes;
        public DinerMenu()
        {
            menuItmes = new MenuItme[Max_Items];
            AddItem("爆炒癞蛤蟆", "讲究火候", false, 42);
            //菜单项...
        }

        public void AddItem(string name, string description, bool vegetarian, double price)
        {
            MenuItme menuItme = new MenuItme(name, description, vegetarian, price);
            if (numberOfImtes >= Max_Items)
            {
                Console.WriteLine("菜单已满");
            }
            else
            {
                menuItmes[numberOfImtes] = menuItme;
                numberOfImtes++;
            }
        }

        public MenuItme[] GetMenuItmes()
        {
            return menuItmes;
        }
    }

  当两个餐馆合并后需要打印早餐和晚餐菜单给顾客用。


            BreakFastMenu breakFastMenu = new BreakFastMenu();
            List<MenuItme> breakFastMenus = breakFastMenu.GetMenuItmes();

            DinerMenu dinerMenu = new DinerMenu();
            MenuItme[] dinerMenus = dinerMenu.GetMenuItmes();
            //打印早餐
            for (int i = 0; i < breakFastMenus.Count; i++)
            {
                Console.WriteLine(breakFastMenus[i].Name);
            }
            //打印晚餐
            for (int i = 0; i < dinerMenus.Length; i++)
            {
                Console.WriteLine(dinerMenus[i].Name);
            } 

按照这种做法我们总是需要处理两个菜单,如果要打印素食,那么也需要循环遍历两个菜单。

假如加入第三家餐厅合并,我们就需要循环处理三次,显然这种方式会让我们系统难以维护。

接下来看我们如何进行改进

二、改进菜单实现

计模式就是要封装变化的部分,很明显,这里变化是:不同的集合类所造成的遍历,我们如何封装遍历集合
不管早餐还是晚餐我们都要用到中括号[ ] 来取菜单项,集合长度来限制长度。
现在我们要创建一个对象,将他称为迭代器(Iterator),利用它来封装“遍历集合内的每个对象的过程”。

  对于List


            Iterator iterator = breakFastMenu.CreateIterator();
            while (iterator.HasNext)
            {
                MenuItme menuItme = iterator.Next();

            }

  对于数组


            Iterator iterator = dinerFastMenu.CreateIterator();
            while (iterator.HasNext)
            {
                MenuItme menuItme = iterator.Next();

            }

现在两个集合的遍历都统一了,而这种方式正是迭代器模式。关于迭代器我们需要知道的第一件事情,就是它依赖于一个迭代器接口。

这个接口可能有HasNext()方法高数我们是否在这个集合中还有更多的元素。

Next()方法返回这个集合中的下一个对象。一旦我们有了这个接口,就可以为各种对象集合实现迭代器。

现在我们对晚餐菜单进行改造,首先我们需要定义一个迭代器接口


    public interface Iterator
    {
        bool HasNext();
        Object Next();
    }

  加入一个晚餐菜单迭代器


    public class DinerMenuIterator : Iterator
    {
        MenuItme[] menuItmes;
        int position = 0;

        public DinerMenuIterator(MenuItme[] menuItmes)
        {
            this.menuItmes = menuItmes;
        }
        public bool HasNext()
        {
            //由于数组是固定长度,不仅要检查数组,还要检查指定位置是否为空,如果为空后面就没有菜单项了
            if (position >= menuItmes.Length || menuItmes[position] == null)
                return false;
            else
                return true;
        }

        public object Next()
        {
            MenuItme menuItme = menuItmes[position];
            position++;
            return menuItme;
        }
    }

  用迭代器改写晚餐菜单


    public class DinerMenu
    {
        static readonly int Max_Items = 6;
        private int numberOfImtes = 0;
        private MenuItme[] menuItmes;
        public DinerMenu()
        {
            menuItmes = new MenuItme[Max_Items];
            AddItem("爆炒癞蛤蟆", "讲究火候", false, 42);
            //菜单项...
        }

        public void AddItem(string name, string description, bool vegetarian, double price)
        {
            MenuItme menuItme = new MenuItme(name, description, vegetarian, price);
            if (numberOfImtes >= Max_Items)
            {
                Console.WriteLine("菜单已满");
            }
            else
            {
                menuItmes[numberOfImtes] = menuItme;
                numberOfImtes++;
            }
        }
        public Iterator CreateIterator()
        {
            return new DinerMenuIterator(menuItmes);
        }
        //public MenuItme[] GetMenuItmes()
        //{
        //    return menuItmes;
        /

本文标题为:C#设计模式实现之迭代器模式

基础教程推荐