Паттерн Итератор на C# на примерах

Паттерн Итератор предоставляет механизм последовательного перебора элементов коллекции без раскрытия ее внутреннего представления.

Кроме того, перебор элементов выполняется объектом итератора, а не самой коллекцией.
Это упрощает интерфейс, и реализацию коллекции, а также способствует более логичному распределению обязанностей. При использовании итераторов коллекция избавляется от одной обязанности поддержки операций перебора данных.

Итератор предоставляет общий интерфейс перебора элементов коллекции, что позволяет применять полиморфизм в коде, использующем элементы коллекции.

 Представим, что у нас есть два класса, реализующие две разных коллекции, суть проблемы состоит в том, чтобы клиент не знал как эти коллекции реализованы, но имел возможность обходить последовательно все коллекции.

Давайте представим ситуацию нас наняли в качестве разработчика для написания программного обеспечения автомата, который будет выводить информацию клиенту о меню, цене и блюдах.

Как мы знаем утром мы не едим мясо, супы итд, потому что это эти блюда употребляем в обед, а завтракаем более легкой пищей. Соответственно для этой ситуации у нас должно быть 2 коллекции, завтрак и обед. Но проблема еще заключается в том, что в автомате до нас реализовали коллекцию завтраков, и менять мы ее не можем. Для решения этих целей и был придуман паттерн Итератор. Мы реализуем интерфейс.

IEnumerator  
using System;
using System.Collections;

namespace Паттерн_Итератор
{
    public class MenuItem
    {
       public string Name { get; }
       public string Description { get; }
       public bool Vegetarian { get; }
       public double Price { get; }

        public MenuItem(string name, string description, bool vegetarian, double price)
        {
            this.Name = name;
            this.Description = description;
            this.Vegetarian = vegetarian;
            this.Price = price;
        }
    }

    public class DinnerMenuIterator : IEnumerator
    {
        MenuItem []items;
        int position = 0;
        public DinnerMenuIterator(MenuItem[] items)
        {
            this.items = items;
        }

        public object Current
        {
            get
            {
                MenuItem menuItem = items[position];
                position++;
                return menuItem;
            }
        }

        public bool MoveNext()
        {
            if (items == null || position >= items.Length)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public void Reset()
        {
            if (position <= 0)
            {
                throw new Exception("Вы не можете удалить товар пока не вызовите MoveNext() ");
            }
            if (items[position - 1] != null)
            {
                for (int i = 0; i < items.Length - 1; i++)
                {
                    items[i] = items[i + 1];
                }
                items[items.Length - 1] = null;
            }
        }
    }

    public class BreakfastMenuIterator : IEnumerator
    {
        ArrayList items;

        int position = 0;

        public BreakfastMenuIterator(ArrayList items)
        {
            this.items = items;
        }

        public object Current
        {
            get
            {
                object menuItem = items[position];
                position++;
                return menuItem;
            }
        }

        public bool MoveNext()
        {
            if (position >= items.Count || items[position] == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }


        public void Reset()
        {
            if (position <= 0)
            {
                throw new Exception("Вы не можете удалить товар пока не вызовите MoveNext() ");
            }
            if (items[position - 1] != null)
            {
                for (int i = 0; i < items.Count-1; i++)
                {
                    items[i] = items[i + 1];
                }
                items[items.Count - 1] = null;
            }
        }
    }

    public class DinnerMenu
    {
        MenuItem[] menuItems;

        public DinnerMenu()
        {
            menuItems = new MenuItem[]
            {
                new MenuItem("Манная каша", "Манная каша на миндальном молоке с ванилью", true, 120),
                new MenuItem("Чечевичный суп", "Чечевичный суп с томатами", true, 150),
                new MenuItem("Суп рассольник", "Постный рассольник", true, 180),
                new MenuItem("Фаршированные перцы", "Фаршированные перцы с грибами и кабачком", true, 230),
                new MenuItem("Овощное рагу", "Овощное рагу с мясом", false, 350),
                new MenuItem("Свинина", "Свинина под лимонной заправкой", false, 550),
            };
        }

        //метод возвращает интерфейс IEnumerator, клиенту не нужно знать ничего о колекции.
        //клиент просто переберает элементы
        public IEnumerator CreateIterator()
        {
            return new DinnerMenuIterator(menuItems);
        }
    }

    public class BreakfastMenu
    {
        ArrayList menuItems;

        public BreakfastMenu()
        {
            menuItems = new ArrayList
            {
                new MenuItem("Блиный гурман", "Блинчики со взбитыми яцами и тостом", true, 130),
                new MenuItem("Обычны завтра из блинов", "Жареный блин с сосиской", true, 130),
                new MenuItem("Блины с черникой", "Блины со свежей черникой", true, 230),
                new MenuItem("Фруктовые блины", "Блины со свежей черникой и клубникой", true, 230)
            };
        }
        //метод возвращает интерфейс IEnumerator, клиенту не нужно знать ничего о колекции.
        //клиент просто переберает элементы
        public IEnumerator CreateIterator()
        {
            return new BreakfastMenuIterator(menuItems);
        }
    }

    public class Automatic
    {
        BreakfastMenu breakfastMenu;
        DinnerMenu dinnerMenu;

        public Automatic(BreakfastMenu breakfastMenu, DinnerMenu dinnerMenu)
        {
            this.breakfastMenu = breakfastMenu;
            this.dinnerMenu = dinnerMenu;
        }

        public void PrintMenu()
        {
            IEnumerator breakfastIterator = breakfastMenu.CreateIterator();
            IEnumerator dinnerIterator = dinnerMenu.CreateIterator();
            Console.WriteLine("Меню\n----\nЗавтрак");
            PrintMenu(breakfastIterator);
            Console.WriteLine("\nОбед");
            PrintMenu(dinnerIterator);
        }

        void PrintMenu(IEnumerator iterator)
        {
            while (iterator.MoveNext())
            {
                MenuItem menuItem = (MenuItem)iterator.Current;
                Console.WriteLine(menuItem.Name+", ");
                Console.WriteLine(menuItem.Price+" -- ");
                Console.WriteLine(menuItem.Description);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BreakfastMenu breakfastMenu = new BreakfastMenu();
            DinnerMenu dinnerfast = new DinnerMenu();
            Automatic automatic = new Automatic(breakfastMenu, dinnerfast);
            automatic.PrintMenu();
            
            Console.ReadKey();
        }
    }
}
Меню
----
Завтрак
Блиный гурман,
130 --
Блинчики со взбитыми яцами и тостом
Обычны завтра из блинов,
130 --
Жареный блин с сосиской
Блины с черникой,
230 --
Блины со свежей черникой
Фруктовые блины,
230 --
Блины со свежей черникой и клубникой

Обед
Манная каша,
120 --
Манная каша на миндальном молоке с ванилью
Чечевичный суп,
150 --
Чечевичный суп с томатами
Суп рассольник,
180 --
Постный рассольник
Фаршированные перцы,
230 --
Фаршированные перцы с грибами и кабачком
Овощное рагу,
350 --
Овощное рагу с мясом
Свинина,
550 --
Свинина под лимонной заправкой

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.