zoukankan      html  css  js  c++  java
  • 10 迭代器模式

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

    实际上现在很多语言都自带迭代器,无需我们单独实现,比如c#中的foreach-in,但通过学习迭代器模式,我们可以看到类似foreach-in这种语法背后的逻辑,同时感受一下GOF所在的那个时代大神们的创造力。

    c#中foreach-in是语言内置迭代器的语法糖,List、数组、Dictionary等等都可以使用foreach方便地遍历,这也正是迭代器的好处,被遍历的对象不需要暴露自己内部的表示,这样遍历的代码就可以和被遍历对象解耦。

    类图如下:

    搜狗截图20161127222409

    示例代码使用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 Name
    13         {
    14             get { return name; }
    15             set { name = value; }
    16         }
    17         string description;
    18 
    19         public string Description
    20         {
    21             get { return description; }
    22             set { description = value; }
    23         }
    24         bool isVegetarian;
    25 
    26         public bool IsVegetarian
    27         {
    28             get { return isVegetarian; }
    29             set { isVegetarian = value; }
    30         }
    31         double price;
    32 
    33         public double Price
    34         {
    35             get { return price; }
    36             set { price = value; }
    37         }
    38     }
    View Code

    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             else
    32             {
    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     }
    View Code

    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     }
    View Code

    迭代器

     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             else
    23             {
    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 : Iterator
    38     {
    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             else
    53             {
    54                 return true;
    55             }
    56         }
    57 
    58         public object Next()
    59         {
    60 
    61             MenuItem item = items[position];
    62             position++;
    63             return item;
    64         }
    65     }
    View Code

    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     }
    View Code

    测试代码

     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     }
    View Code

    单一职责原则:一个类应该只有一个引起变化的原因。

    比如前文中的菜单,使用迭代器之前,菜单既要负责存储项目,又要负责展示,每次给菜单新增内容时都要都是修改这两方面的功能,造成了维护上的不便,而维护上的不便有可能带来逻辑上的混乱进而引发bug。可见,单一职责原则是很有指导意义的。

  • 相关阅读:
    洛谷 2574 XOR的艺术
    洛谷 1774 最接近神的人
    洛谷 3398 仓鼠找sugar 【模板】判断树上两链有交
    洛谷 2440 木材加工
    洛谷 1824 进击的奶牛
    洛谷 1873 砍树
    洛谷 1577 切绳子
    51nod1485 字母排序
    51nod1055 最长等差数列
    51nod1128 正整数分组V2
  • 原文地址:https://www.cnblogs.com/zhixin9001/p/6107687.html
Copyright © 2011-2022 走看看