Рубрики

Образец итератора

Шаблон Iterator — это относительно простой и часто используемый шаблон проектирования. Есть много структур данных / коллекций, доступных на каждом языке. Каждая коллекция должна предоставлять итератор, который позволяет ей перебирать свои объекты. Однако при этом следует убедиться, что он не раскрывает свою реализацию.
Предположим, мы создаем приложение, которое требует от нас вести список уведомлений. В конце концов, некоторая часть вашего кода потребует перебора всех уведомлений. Если бы мы реализовали вашу коллекцию уведомлений как массив, вы бы перебрали их как:

// If a simple array is used to store notifications
for (int i = 0; i < notificationList.length; i++)
     Notification notification = notificationList[i]);

// If ArrayList is Java is used, then we would iterate
// over them as:
for (int i = 0; i < notificationList.size(); i++)
    Notification notification = (Notification)notificationList.get(i);

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

// Create an iterator
Iterator iterator = notificationList.createIterator();

// It wouldn’t matter if list is Array or ArrayList or
// anything else.
while (iterator.hasNext())
{
    Notification notification = iterator.next());
}

Шаблон Iterator позволяет нам сделать это. Формально это определяется как ниже:

Здесь у нас есть общий интерфейс Aggregate для клиента, так как он отделяет его от реализации вашей коллекции объектов. ConcreteAggregate реализует createIterator (), который возвращает итератор для своей коллекции. Ответственность каждого ConcreteAggregate заключается в создании экземпляра ConcreteIterator, который может выполнять итерацию по своей коллекции объектов. Интерфейс итератора предоставляет набор методов для обхода или изменения коллекции, в дополнение к next () / hasNext (), он также может предоставлять функции для поиска, удаления и т. Д.
Давайте разберемся в этом на примере. Предположим, мы создаем панель уведомлений в нашем приложении, которая отображает все уведомления, которые содержатся в коллекции уведомлений. NotificationCollection предоставляет итератор для итерации по своим элементам без раскрытия информации о том, как он реализовал коллекцию (в данном случае массив) для клиента (NotificationBar).

Диаграмма классов будет такой:

Ниже приведена реализация того же Java:

// Java-программа для демонстрации реализации
// шаблона итератора на примере
// уведомления

  
// Простой класс уведомлений

class Notification

{

    // Для хранения уведомлений

    String notification;

  

    public Notification(String notification)

    {

        this.notification = notification;

    }

    public String getNotification()

    {

        return notification;

    }

}

  
// Интерфейс коллекции

interface Collection

{

    public Iterator createIterator();

}

  
// Сборник уведомлений

class NotificationCollection implements Collection

{

    static final int MAX_ITEMS = 6;

    int numberOfItems = 0;

    Notification[] notificationList;

  

    public NotificationCollection()

    {

        notificationList = new Notification[MAX_ITEMS];

  

        // Давайте добавим несколько фиктивных уведомлений

        addItem("Notification 1");

        addItem("Notification 2");

        addItem("Notification 3");

    }

  

    public void addItem(String str)

    {

        Notification notification = new Notification(str);

        if (numberOfItems >= MAX_ITEMS)

            System.err.println("Full");

        else

        {

            notificationList[numberOfItems] = notification;

            numberOfItems = numberOfItems + 1;

        }

    }

  

    public Iterator createIterator()

    {

        return new NotificationIterator(notificationList);

    }

}

  
// Мы также могли бы использовать Java.Util.Iterator

interface Iterator

{

    // указывает, есть ли еще элементы для

    // перебирать

    boolean hasNext();

  

    // возвращает следующий элемент

    Object next();

}

  
// Итератор уведомлений

class NotificationIterator implements Iterator

{

    Notification[] notificationList;

  

    // поддерживает текущее положение итератора над массивом

    int pos = 0;

  

    // Конструктор принимает массив notifiactionList

    // собираемся перебрать

    public  NotificationIterator (Notification[] notificationList)

    {

        this.notificationList = notificationList;

    }

  

    public Object next()

    {

        // возвращаем следующий элемент в массиве и увеличиваем pos

        Notification notification =  notificationList[pos];

        pos += 1;

        return notification;

    }

  

    public boolean hasNext()

    {

        if (pos >= notificationList.length ||

            notificationList[pos] == null)

            return false;

        else

            return true;

    }

}

  
// Содержит коллекцию уведомлений как объект
// NotificationCollection

class NotificationBar

{

    NotificationCollection notifications;

  

    public NotificationBar(NotificationCollection notifications)

    {

        this.notifications = notifications;

    }

  

    public void printNotifications()

    {

        Iterator iterator = notifications.createIterator();

        System.out.println("-------NOTIFICATION BAR------------");

        while (iterator.hasNext())

        {

            Notification n = (Notification)iterator.next();

            System.out.println(n.getNotification());

        }

    }

}

  
// Класс водителя

class Main

{

    public static void main(String args[])

    {

        NotificationCollection nc = new NotificationCollection();

        NotificationBar nb = new NotificationBar(nc);

        nb.printNotifications();

    }

}

Выход:

-------NOTIFICATION BAR------------
Notification 1
Notification 2
Notification 3

Обратите внимание, что если бы мы использовали ArrayList вместо Array, клиентский код (панель уведомлений) не изменился бы из-за развязки, достигнутой с помощью интерфейса итератора.

Ссылки:
Head First Design Patterns

Эта статья предоставлена Сулабх Кумар. Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью и отправить ее по почте на contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

Образец итератора

0.00 (0%) 0 votes