This is the 7th day of my participation in the August Text Challenge.More challenges in August

Preface: the iterator pattern is not used much, because both C# and Java have been wrapped for me, but do you know the nature of the things you often use?

You can see how C# foreach loops are implemented by looking at the iterator pattern. My other article on the nature of C# foreach loops and enumerators explains the nature of foreach, which uses the iterator pattern.

By convention, the example goes up. (write a few hours browser crash, I see in the auto save ah, the result has no content, again masturbate a concise point of it)

 

1. Restaurant menu consolidation

Now there are two restaurants, one for breakfast and one for dinner. They all have their own way of managing the menu, and now the two restaurants have merged and they need to unify the menu, so let me see what they look like in the original.

The menu items on both menus are the same

A menu item

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; }}Copy the code

Breakfast menu, using List management, unlimited length

public class BreakFastMenu { private List<MenuItme> menuItmes; public BreakFastMenu() { menuItmes = new List<MenuItme>(); AddItem(" Meatloaf ", "yummy ", false, 7); // Menu item... } 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; }}Copy the code

Dinner menu, using array management, limit length to 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(" Stir-fry toad ", "Pay attention to the heat ", false, 42); // Menu item... } 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(" Menu is full "); } else { menuItmes[numberOfImtes] = menuItme; numberOfImtes++; } } public MenuItme[] GetMenuItmes() { return menuItmes; }}Copy the code

When the two restaurants merged, they had to print out breakfast and dinner menus for customers.

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); } // Print dinner for (int I = 0; i < dinerMenus.Length; i++) { Console.WriteLine(dinerMenus[i].Name); }Copy the code

In this way we always need to deal with two menus, and if we want to print vegetarian, we also need to loop through both menus.

If we add a third restaurant merge, we need to recycle three times, which obviously makes our system difficult to maintain.

Now how can we improve

Second, improve menu implementation

How do we encapsulate the traversal set caused by different sets of classes

For both breakfast and dinner we use brackets [] to take menu items and set length to limit length.

Now we’ll create an object, call it an Iterator, that encapsulates “the process of walking through every object in the collection.”

For the List

            Iterator iterator = breakFastMenu.CreateIterator();
            while (iterator.HasNext)
            {
                MenuItme menuItme = iterator.Next();

            }
Copy the code

  

For an array of

            Iterator iterator = dinerFastMenu.CreateIterator();
            while (iterator.HasNext)
            {
                MenuItme menuItme = iterator.Next();

            }
Copy the code

The traversal of both sets is now uniform, and this is the iterator pattern. The first thing we need to know about iterators is that they depend on an iterator interface.

This interface may have a HasNext() method and it’s not clear if we have any more elements in this set.

The Next() method returns the Next object in the collection. Once we have this interface, we can implement iterators for various collections of objects.

Now to transform the dinner menu, first we need to define an iterator interface

    public interface Iterator
    {
        bool HasNext();
        Object Next();
    }
Copy the code

Add a dinner menu iterator

public class DinerMenuIterator : Iterator { MenuItme[] menuItmes; int position = 0; public DinerMenuIterator(MenuItme[] menuItmes) { this.menuItmes = menuItmes; } public bool HasNext() {// Because the array is fixed length, check not only the array, but also the specified position is empty, If is empty behind, there is no menu item if (position > = menuItmes. Length | | menuItmes [position] = = null) return false. else return true; } public object Next() { MenuItme menuItme = menuItmes[position]; position++; return menuItme; }}Copy the code

Rewrite the dinner menu with iterators

public class DinerMenu { static readonly int Max_Items = 6; private int numberOfImtes = 0; private MenuItme[] menuItmes; public DinerMenu() { menuItmes = new MenuItme[Max_Items]; AddItem(" Stir-fry toad ", "Pay attention to the heat ", false, 42); // Menu item... } 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(" Menu is full "); } else { menuItmes[numberOfImtes] = menuItme; numberOfImtes++; } } public Iterator CreateIterator() { return new DinerMenuIterator(menuItmes); } //public MenuItme[] GetMenuItmes() //{ // return menuItmes; / /}}Copy the code

Similarly, we added iterators for breakfast

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; }}Copy the code

Rewrite the breakfast menu with iterators

public class BreakFastMenu { private List<MenuItme> menuItmes; public BreakFastMenu() { menuItmes = new List<MenuItme>(); AddItem(" Meatloaf ", "yummy ", false, 7); // Menu item... } 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; / /}}Copy the code

Ok, let’s try the iterator in action

 

Iterator pattern

After the second step, we have basically implemented the iterator mode. Finally, we will improve the print menu and manage the unified interface for the menu.

Define a Menu interface

     public interface Menu
    {
        Iterator CreateIterator();
    }
Copy the code

Let breakfast and dinner are implemented Menu interface, and package a new Menu print

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(" new menu -------- breakfast "); PrintMenu(breakFastIterator); Console.WriteLine(" New menu -------- dinner "); Iterator dinerIterator = dinerMenu.CreateIterator(); PrintMenu(dinerIterator); } private void PrintMenu(Iterator Iterator) {while (iterator.hasnext ()) {// Get next item MenuItme MenuItme = (MenuItme)iterator.Next(); Console.WriteLine(menuItme.Name); }}}Copy the code

  

Iterator pattern definition:

Iterator pattern: Provides a way to access the elements of a collection object sequentially without exposing their internal representation.

The iterator pattern allows us to walk around each element in the collection without exposing its internal representation.

Place the task of walking on the iterator, not the collection. This simplifies the interface and implementation of collections and puts responsibilities in their place.