你的位置:首页 > ASP.net教程

[ASP.net教程]《Head First设计模式》C#实现(四)——迭代器模式


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

  

  煎饼屋和餐厅合并了!但是有个小问题,虽然两家都同意实现相同的菜单项MenuItem,但是煎饼屋想使用ArrayList储存菜单项,而餐厅则使用数组,为了使女招待能同时访问两家的菜单,我们需要为菜单提供一个统一的访问接口。

  先来看菜单项MenuItem,两家店的实现相同

class MenuItem  {    string name;//名称    string description;//描述    bool vegetarian;//是否是素食    double price;//价格    public MenuItem(string name, string description, bool vegetarian, double price)    {      this.name = name;      this.description = description;      this.vegetarian = vegetarian;      this.price = price;    }    public string getName()    {      return name;    }    public string getDescription()    {      return description;    }    public double getPrice()    {      return price;    }    public bool isVegetarian()    {      return vegetarian;    }     }

  接口Menu,它只定义了一个创建迭代器的方法,实现这个接口的类将提供各自不同的迭代器

 interface Menu  {     Iterator createIterator();  }

  煎饼屋菜单,实现了Menu接口

class PancakeHouseMenu : Menu  {    ArrayList menuItems;    public PancakeHouseMenu()    {      menuItems = new ArrayList();      addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs,and toast", true, 2.99);      addItem("Regular Pancake Breakfast", "Pancakes with fired eggs,and sausage", false, 2.99);      addItem("Blueberry Pancake", "Pancakes with fresh blueberries", true, 3.49);      addItem("Waffles", "Waffles,with your choice of blueberries or strawberries", true, 3.59);    }    public void addItem(string name, string description, bool vegetarian, double price)    {      MenuItem menuItem = new MenuItem(name, description, vegetarian, price);      menuItems.Add(menuItem);    }        public Iterator createIterator()    {      return new PancakeHouseIterator(menuItems);    }    //菜单的其他方法  }

  餐厅菜单同样如此

 class DinerMenu : Menu  {    static int Max_ITEMS = 6;    int numberOfItems = 0;    MenuItem[] menuItems;    public DinerMenu()    {      menuItems = new MenuItem[Max_ITEMS];      addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);      addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99);      addItem("Soup of the day", "Soup of the day,whit a side of potato salad", false, 3.29);      addItem("Hot dog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05);    }    public void addItem(string name, string description, bool vegetarian, double price)    {      MenuItem menuItem = new MenuItem(name, description, vegetarian, price);      if (numberOfItems >= Max_ITEMS)      {        Console.WriteLine("Sorry,menu is full! Can't add item to menu!");      }      else      {        menuItems[numberOfItems] = menuItem;        numberOfItems++;      }    }    public MenuItem[] getMenuItems()    {      return menuItems;    }    public Iterator createIterator()    {      return new DinerMenuIterator(menuItems);    }    //菜单的其他方法  }  

  接下来看看迭代器,迭代器有一个接口,定义了一些操作

interface Iterator  {    bool hasNext();    object next();    //更多的方法,例如remove...  }

  不同的菜单有不同的迭代器,这是煎饼屋的

 class PancakeHouseIterator:Iterator  {    ArrayList items;    int position = 0;    public PancakeHouseIterator(ArrayList items)    {      this.items = items;    }    public object next()    {      MenuItem menuItem = (MenuItem)items[position];      position++;      return menuItem;    }    public bool hasNext()    {      if (position>=items.Count)      {        return false;      }      else      {        return true;      }    }  }

  这是餐厅的

class DinerMenuIterator:Iterator  {    MenuItem[] items;    int position = 0;    public DinerMenuIterator(MenuItem[] items)    {      this.items = items;    }    public object next()    {      MenuItem menuItem = items[position];      position++;      return menuItem;    }    public bool hasNext()    {      if (position>=items.Length||items[position]==null)      {        return false;      }      else      {        return true;      }    }  }

  选择女招待可以方便的用统一的方法操作两家的菜单了

class Waitress  {    Menu pancakeHouseMenu;    Menu dinerMenu;    public Waitress(Menu pancake, Menu diner)    {      this.pancakeHouseMenu = pancake;      this.dinerMenu = diner;    }    public void printMenu()    {      Iterator pancakeIterator = pancakeHouseMenu.createIterator();      Iterator dinerIterator = dinerMenu.createIterator();      Console.WriteLine("MENU\n----\nBREAKFAT");      printMenu(pancakeIterator);      Console.WriteLine("\nLUNCH");      printMenu(dinerIterator);    }    private void printMenu(Iterator iterator)    {      while (iterator.hasNext())      {        MenuItem menuItem = (MenuItem)iterator.next();        Console.Write(menuItem.getName() + ",");        Console.WriteLine(menuItem.getPrice() + "-- ");        Console.WriteLine("   "+menuItem.getDescription());      }    }  }

  迭代器的好处是将来如果有新的菜单加入,而它使用了不同的存储方法(例如hashtable),只需要让它实现迭代器接口,而不必修改女招待的操作方式。