首页 > 代码库 > 10 迭代器模式
10 迭代器模式
迭代器模式(Iterator)定义:提供一种顺序访问聚合对象中各个元素的方法,而又不暴露其内部的表示。
实际上现在很多语言都自带迭代器,无需我们单独实现,比如c#中的foreach-in,但通过学习迭代器模式,我们可以看到类似foreach-in这种语法背后的逻辑,同时感受一下GOF所在的那个时代大神们的创造力。
c#中foreach-in是语言内置迭代器的语法糖,List、数组、Dictionary等等都可以使用foreach方便地遍历,这也正是迭代器的好处,被遍历的对象不需要暴露自己内部的表示,这样遍历的代码就可以和被遍历对象解耦。
类图如下:
示例代码使用Head Forst设计模式中的例子,煎饼屋的菜单PancakeHouseMenu使用List存放,餐厅的菜单DinerMenu使用数组存放,两者合并后,为了能够统一地展示他们的菜单项,使用迭代器模式处理
代码如下:
MenuItem规定了菜单的统一格式
1 class MenuItem 2 { 3 public MenuItem(string name, string description, bool isVegetarian, double price) 4 { 5 this.name = name; 6 this.description = description; 7 this.isVegetarian = isVegetarian; 8 this.price = price; 9 }10 string name;11 12 public string Name13 {14 get { return name; }15 set { name = value; }16 }17 string description;18 19 public string Description20 {21 get { return description; }22 set { description = value; }23 }24 bool isVegetarian;25 26 public bool IsVegetarian27 {28 get { return isVegetarian; }29 set { isVegetarian = value; }30 }31 double price;32 33 public double Price34 {35 get { return price; }36 set { price = value; }37 }38 }
DinerMenu类
1 class DinerMenu 2 { 3 static readonly int MAX_ITEMS = 6; 4 int numberOfItems = 0; 5 MenuItem[] menuItem; 6 public DinerMenu() 7 { 8 menuItem = new MenuItem[MAX_ITEMS]; 9 AddItem("Vegetarian BLT",10 "(Fakin‘) Bacon with lettuce&tomato on whole wheat",11 true, 2.99);12 AddItem("BLT",13 "Bacon with lettuce&tomato on whole wheat",14 false, 2.99);15 AddItem("Soup of the Day",16 "Soup of the Day, with a side of potato salad",17 false, 3.29);18 AddItem("HotDog",19 "A hot dog, with saurkraut, relish, onions, topped with chesse",20 false, 3.05);21 22 }23 24 public void AddItem(string name, string description, bool isVegetarian, double price)25 {26 MenuItem item = new MenuItem(name, description, isVegetarian, price);27 if (numberOfItems >= MAX_ITEMS)28 {29 Console.WriteLine("Over Flow!!!");30 }31 else32 {33 menuItem[numberOfItems] = item;34 numberOfItems++;35 }36 }37 38 public MenuItem[] GetMenuItems()39 {40 return menuItem;41 }42 43 public Iterator CreateIterator()44 {45 return new DinerMenuIterator(menuItem);46 }47 }
PancakeHouseMenu类
1 class PancakeHouseMenu 2 { 3 List<MenuItem> listMenu = new List<MenuItem>(); 4 public PancakeHouseMenu() 5 { 6 MenuItem item = new MenuItem( 7 "K&B‘s Pancake Breakfast", 8 "Pancakes with scrambled eggs, and toast", 9 true,10 2.99);11 listMenu.Add(item);12 item = new MenuItem(13 "Regular Pancake Breakfast",14 "Pancakes with fired eggs, sausage",15 false,16 2.99);17 listMenu.Add(item);18 item = new MenuItem(19 "Blueberry Pancake",20 "Pancakes made with fresh blueberry",21 true,22 3.49);23 listMenu.Add(item);24 item = new MenuItem(25 "Waffles",26 "Waffles, with your choice of blueberries or strawberries",27 true,28 3.59);29 listMenu.Add(item);30 }31 32 public void AddItem(string name, string description, bool isVegetarian, double price)33 {34 MenuItem item = new MenuItem(name, description, isVegetarian, price);35 listMenu.Add(item);36 }37 public List<MenuItem> GetMenu()38 {39 return listMenu;40 }41 42 public Iterator CreateIterator()43 {44 return new PancakeHouseIterator(listMenu);45 }46 }
迭代器
1 interface Iterator 2 { 3 bool HaveNext(); 4 object Next(); 5 } 6 7 class DinerMenuIterator : Iterator 8 { 9 MenuItem[] items;10 int position = 0;11 public DinerMenuIterator(MenuItem[] items)12 {13 this.items = items;14 }15 16 public bool HaveNext()17 {18 if (position >= items.Length || items[position] == null)19 {20 return false;21 }22 else23 {24 return true;25 }26 }27 28 public object Next()29 {30 31 MenuItem item = items[position];32 position++;33 return item;34 }35 }36 37 class PancakeHouseIterator : Iterator38 {39 List<MenuItem> items;40 int position = 0;41 public PancakeHouseIterator(List<MenuItem> items)42 {43 this.items = items;44 }45 46 public bool HaveNext()47 {48 if (position >= items.Count)49 {50 return false;51 }52 else53 {54 return true;55 }56 }57 58 public object Next()59 {60 61 MenuItem item = items[position];62 position++;63 return item;64 }65 }
Waitress,服务员,相当于迭代器的使用者
1 class Waitress 2 { 3 DinerMenu dinerMenu; 4 PancakeHouseMenu pancakeMenu; 5 public Waitress(DinerMenu dinerMenu, PancakeHouseMenu pancakeMenu) 6 { 7 this.dinerMenu = dinerMenu; 8 this.pancakeMenu = pancakeMenu; 9 }10 public void PrintMenu()11 {12 Iterator dinerIterator = dinerMenu.CreateIterator();13 Iterator pancakeIterator = pancakeMenu.CreateIterator();14 Console.WriteLine("Diner@@@@@@@");15 PrineMenu(dinerIterator);16 Console.WriteLine("Pancake@@@@@@");17 PrineMenu(pancakeIterator);18 }19 20 private void PrineMenu(Iterator iterator)21 {22 while (iterator.HaveNext())23 {24 MenuItem item = (MenuItem)iterator.Next();25 Console.WriteLine(string.Format("{0} {1} {2}",item.Name,item.Description,item.Price));26 }27 }28 }
测试代码
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 DinerMenu dinerMenu = new DinerMenu(); 6 PancakeHouseMenu pancakeMenu = new PancakeHouseMenu(); 7 Waitress waitress = new Waitress(dinerMenu, pancakeMenu); 8 waitress.PrintMenu(); 9 Console.ReadKey();10 }11 }
单一职责原则:一个类应该只有一个引起变化的原因。
比如前文中的菜单,使用迭代器之前,菜单既要负责存储项目,又要负责展示,每次给菜单新增内容时都要都是修改这两方面的功能,造成了维护上的不便,而维护上的不便有可能带来逻辑上的混乱进而引发bug。可见,单一职责原则是很有指导意义的。
10 迭代器模式
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。