博客
关于我
Head First设计模式——迭代器模式
阅读量:397 次
发布时间:2019-03-06

本文共 7652 字,大约阅读时间需要 25 分钟。

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

看完迭代器模式你就知道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
menuItmes; public BreakFastMenu() { menuItmes = new List
(); 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
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
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
menuItmes; int position = 0; public BreakFastIterator(List
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
menuItmes; public BreakFastMenu() { menuItmes = new List
(); 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
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);            }        }    }

  

迭代器模式定义:

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

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

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

转载地址:http://vqbkz.baihongyu.com/

你可能感兴趣的文章
华为云FusionInsight湖仓一体解决方案的前世今生
查看>>
大数据处理黑科技:揭秘PB级数仓GaussDB(DWS) 并行计算技术
查看>>
C++调用Go方法的字符串传递问题及解决方案
查看>>
云原生2.0时代下,DevOps实践如何才能更加高效敏捷?
查看>>
技巧收藏|10个JavaScript常用数组操作方法
查看>>
两种端到端通用目标检测方法
查看>>
探索语言交互技术在政务数字化的应用
查看>>
让 AI “潜入”物流中心,你的快递很快就到!
查看>>
云小课 | 守护网络安全不是问题,iptables的四表五链为你开启“八卦阵”
查看>>
LiteOS内核源码分析:任务栈信息
查看>>
23种设计模式之迭代器模式
查看>>
23种设计模式之组合模式
查看>>
mysql zip安装
查看>>
mysql修改密码
查看>>
virtualbox中 Kali Linux安装增强功能
查看>>
virtualbox中 Ubuntu挂载共享文件夹
查看>>
Python 内置函数笔记
查看>>
BootStrapTable 错误
查看>>
PHP 中的Trait
查看>>
PHP 配置文件
查看>>