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;
        //}
    }

  同理我们为早餐加入迭代器

    public class BreakFastIterator: Iterator
    {
        List<MenuItme> menuItmes;
        int position = 0;

        public BreakFastIterator(List<MenuItme> menuItmes)
        {
            this.menuItmes = menuItmes;
        }
        public bool HasNext()
        {
            if (position >= menuItmes.Count)
                return false;
            else
                return true;
        }

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

  用迭代器改写早餐菜单

    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 Iterator CreateIterator()
        {
            return new BreakFastIterator(menuItmes);
        }
        //public List<MenuItme> GetMenuItmes()
        //{
        //    return menuItmes;
        //}
    }

  好了,让我们试一试迭代器工作情况

三、迭代器模式

经过第二步我们基本已经实现迭代器模式,最后我们再改良一下打印菜单,并对菜单进行统一接口的管理。

定义一个Menu接口

     public interface Menu
    {
        Iterator CreateIterator();
    }

让早餐晚餐都实现Menu接口,并封装一个新的菜单打印

    public class NewMenu
    {
        Menu breakFastMenu;
        Menu dinerMenu;
        public NewMenu(Menu breakFastMenu, Menu dinerMenu) {
            this.breakFastMenu = breakFastMenu;
            this.dinerMenu = dinerMenu;
        }

        public void PrintMenu() {

            Iterator breakFastIterator = breakFastMenu.CreateIterator();
            Console.WriteLine("新菜单--------早餐");
            PrintMenu(breakFastIterator);
            Console.WriteLine("新菜单--------晚餐");
            Iterator dinerIterator = dinerMenu.CreateIterator();
            PrintMenu(dinerIterator);
        }

        private void PrintMenu(Iterator iterator) {
            while (iterator.HasNext())
            {
                //取得下一个项
                MenuItme menuItme = (MenuItme)iterator.Next();
                Console.WriteLine(menuItme.Name);
            }
        }
    }

迭代器模式定义:

迭代器模式:提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示。

迭代器模式让我们能游走于集合内的每一个元素,而又不暴露其内部的表示。

把游走的任务放在迭代器上,而不是集合上。这样简化了集合的接口和实现,也让责任各得其所。

总结

到此这篇关于C#设计模式实现之迭代器模式的文章就介绍到这了,更多相关C#迭代器模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C#迭代器模式(Iterator Pattern)实例教程

    本文以实例形式简单简述了C#迭代器模式的实现方法,分享给大家供大家参考.具体方法如下: 一般来说,迭代器模式的需求来自:需要对一些集合进行迭代,而迭代的方式可能有很多种. 说到迭代,动作大致包括设置第一个位置,获取下一个位置元素,判断是否迭代结束,获取当前位置元素,大致就这么些.把这些迭代动作封装到一个接口中. public interface IIterator { void First(); string Next(); bool IsDone(); string Current(); }

  • C#学习笔记整理-迭代器模式介绍

    什么是迭代器模式? 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示. 何时使用迭代器模式? 当需要访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,需要考虑使用迭代器模式. 迭代器模式的组成 Iterator:迭代器抽象类,用于定义得到开始对象,对到下一个对象,判断是否到结尾,当前对象等抽象方法,统一接口. ConcreteAggregate:保存聚合对象. ConcreteIterator:继承于Iterator,实现具体如何对聚

  • PHP设计模式入门之迭代器模式原理与实现方法分析

    本文实例讲述了PHP设计模式入门之迭代器模式.分享给大家供大家参考,具体如下: 在深入研究这个设计模式之前,我们先来看一道面试题,来自鸟哥的博客, 题目是这样的: 使对象可以像数组一样进行foreach循环,要求属性必须是私有. 不使用迭代器模式很难实现,先看实现的代码: sample.php <?php class Sample implements Iterator{ private $_arr; public function __construct(Array $arr){ $this-

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

    目录 前言: 一.餐馆合并菜单 二.改进菜单实现 三.迭代器模式 总结 前言: 迭代器模式平时用的不多,因为不管C#还是Java都已经帮我封装了,但是你是否知道平时经常在用的东西本质是怎么回事呢. 看完迭代器模式你就知道C# foreach循环是怎么实现的了,我的另一篇C# Foreach循环本质与枚举器就讲解了foreach的本质,其中用到的就是迭代器模式. 按照惯例,例子走起.(写了几个小时浏览器崩溃,我看见在自动保存啊,结果没内容,再撸一遍精简点的吧) 一.餐馆合并菜单 现在有两个餐馆和并

  • PHP设计模式之PHP迭代器模式讲解

    迭代器有时又称光标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如list或vector)上遍访的接口,设计人员无需关心容器物件的内容. 各种语言实作Iterator的方式皆不尽同,有些面向对象语言像Java, C#, Python, Delphi都已将Iterator的特性内建语言当中,完美的跟语言整合,我们称之隐式迭代器(implicit iterator),但像是C++语言本身就没有Iterator的特色,但STL仍利用template实作了功能强大的ite

  • Java设计模式之java迭代器模式详解

    目录 前言 介绍 角色 迭代器模式中的工厂模式 学院遍历的案例 分析 解决方案 基本介绍 原理类图 上面案例的类图 案例实现代码 案例总结 应用实例 Java集合中的迭代器模式 角色说明 Mybatis中的迭代器模式 优点 缺点 总结 前言 很早之前,我们的电视调节频道是需要用电视上的按钮去控制的,那时并没有遥控器,如果我们想要调台,只能一次又一次的拧按钮. 越来越高级的电视机相继出现,现在的电话机,我们有了电视遥控器,我们使用电视遥控器来调台,这个时候,无需直接操作电视. 我们可以将电视机看成

  • 设计模式中的迭代器模式在Cocoa Touch框架中的使用

    基本理解 迭代器模式(Iterrator):提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露该元素的内部表示. 当你访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式. 你需要对聚集有多种方式遍历时,可以考虑用迭代器模式. 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据. 迭代器定义了一个用于访问集合元素并记录当前元素的接口. 不同的迭代器可以执行不同的迭代策略.

  • Android编程设计模式之迭代器模式详解

    本文实例讲述了Android编程设计模式之迭代器模式.分享给大家供大家参考,具体如下: 一.介绍 迭代器模式(Iterator Pattern)又称为游标(Cursor)模式,是行为型设计模式之一.迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如Java中的List.Map.数组等,我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法.如果我们将遍历的方法封装到容器中,那么对于容器类来说就承担了过多的功能,容器类不仅要维护自身内部的数据元

  • PHP设计模式之迭代器模式的使用

    一说到这个模式,就不得不提循环语句.在<大话设计模式>中,作者说道这个模式现在的学习意义更大于实际意义,这是为什么呢?当然就是被foreach这货给整得.任何语言都有这种类似的语法可以方便快捷的对数组.对象进行遍历,从而让迭代器模式从高高在上的23大设计模式中的明星慢慢成为了路人.特别是我们这门PHP语言,PHP的强大之处就在于对于数组的灵活操作,本身就是hashmap的结构,自然会有各种方便的数组操作语法,而foreach也是我们最常用的语句,甚至比for还常用. Gof类图及解释 GoF定

  • Java设计模式之迭代器模式

    本文介绍设计模式中的迭代器模式,首先通俗的解释迭代器模式的基本概念和对应的四个角色,并根据四个角色举一个典型的实例,为了加强知识的连贯性,我们以Jdk源码集合中使用迭代器模式的应用进一步说明,最后说明迭代器模式的应用场景和优缺点. 读者可以拉取完整代码本地学习,实现代码均测试通过上传到码云,本地源码下载. 一.概念理解 迭代器模式官方解释就是提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示.何为聚合对象呢?最典型的就是集合类. 大白话也就是,集合中的数据是私有的,集合中不

  • java 迭代器模式实例详解

    java 迭代器模式实例详解 今天来818设计模式中的迭代器模式,也是java中Stack,List,Set等接口以及数组这个数据结构都会使用的一种模式. 首先,为什么使用迭代器模式,目的就是通过一个通用的迭代方法,隐藏stack,list,set以及数组中不同的遍历细节.也就是说,我不想让那些调用我的遍历容器的方法的人知道我到底是怎么一个一个的获取这些元素的(stack的pop,list的get,数组的array[i]),我只想让他知道他能 通过一个迭代器Iterator或者通过一个for e

  • Java设计模式之迭代器模式_动力节点Java学院整理

    定义:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节. 类型:行为类模式 类图: 如果要问Java中使用最多的一种模式,答案不是单例模式,也不是工厂模式,更不是策略模式,而是迭代器模式,先来看一段代码吧: public static void print(Collection coll){ Iterator it = coll.iterator(); while(it.hasNext()){ String str = (String)it.next(); System.out

随机推荐