Как реализовать курсор итератор? - PullRequest
0 голосов
/ 09 ноября 2019

В разделе «Структура» шаблона проектирования Итератор книга Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения определяет Iteratorкласс с четырьмя основными операциями: First, Next, IsDone и CurrentItem.

В разделе «Реализация» книга содержит следующий элемент :

Кто определяет алгоритм обхода? Итератор - не единственное место, где можно определить алгоритм обхода. Агрегат может определять алгоритм обхода и использовать итератор для хранения только состояния итерации. Мы называем этот тип итератора курсор , так как он просто указывает на текущую позицию в совокупности. Клиент вызовет операцию Next в агрегате с курсором в качестве аргумента, а операция Next изменит состояние курсора.

Если итератор отвечает за алгоритм обхода, тоЛегко использовать разные алгоритмы итерации в одном агрегате, а также проще использовать один и тот же алгоритм в разных агрегатах. С другой стороны, алгоритму обхода может потребоваться доступ к закрытым переменным агрегата. В этом случае размещение алгоритма обхода в итераторе нарушает инкапсуляцию агрегата.

Но примерная реализация итератора курсора не предоставляется.

Кто должен предоставлять интерфейс для управления итерацией, итератором курсора или агрегатом?

Ниже приведен пример реализации двух альтернатив в Python.

  • Если итератор курсора предоставляет интерфейс итерации, в дополнение к операциям GetState и SetState он должен определять First, Next, IsDone и CurrentItemбазовые операции и делегирование соответствующим агрегатным операциям:

    class Iterator:
    
        def __init__(self, aggregate):
            self.__aggregate = aggregate
    
        def first(self):
            self.__aggregate._first(self)
    
        def next(self):
            self.__aggregate._next(self)
    
        def is_done(self):
            return self.__aggregate._is_done(self)
    
        def current_item(self):
            return self.__aggregate._current_item(self)
    
        def _get_state(self):
            return self.__state
    
        def _set_state(self, state):
            self.__state = state
    

    И агрегат должен определять те же базовые операции, которые извлекают и обновляют состояние итератора курсора, используя его операции GetState и SetState:

    class Aggregate:
    
        def __init__(self, list):
            self.__list = list
    
        def _first(self, iterator):
            iterator._set_state(0)
    
        def _next(self, iterator):
            iterator._set_state(iterator._get_state() + 1)
    
        def _is_done(self, iterator):
            return iterator._get_state() >= len(self.__list)
    
        def _current_item(self, iterator):
            if self._is_done(iterator):
                raise ValueError
    
            return self.__list[iterator._get_state()]
    
        def create_iterator(self):
            return Iterator(self)
    

    Затем клиент будет использовать итератор курсора для управления итерацией:

    aggregate = Aggregate(["foo", "bar", "baz", "qux"])
    iterator = aggregate.create_iterator()
    iterator.first()
    
    while not iterator.is_done():
        print(iterator.current_item())
        iterator.next()
    
  • Если совокупность предоставляет tВ итерационном интерфейсе итератор курсора должен определять операции GetState и SetState:

    class Iterator:
    
        def _get_state(self):
            return self.__state
    
        def _set_state(self, state):
            self.__state = state
    

    И агрегат должен определять First, Next, IsDone и CurrentItem basicоперации, которые извлекают и обновляют состояние итератора курсора, используя его операции GetState и SetState:

    class Aggregate:
    
        def __init__(self, list):
            self.__list = list
    
        def first(self, iterator):
            iterator._set_state(0)
    
        def next(self, iterator):
            iterator._set_state(iterator._get_state() + 1)
    
        def is_done(self, iterator):
            return iterator._get_state() >= len(self.__list)
    
        def current_item(self, iterator):
            if self.is_done(iterator):
                raise ValueError
    
            return self.__list[iterator._get_state()]
    
        def create_iterator(self):
            return Iterator()
    

    Затем клиент будет использовать агрегат для управления итерацией:

    aggregate = Aggregate(["foo", "bar", "baz", "qux"])
    iterator = aggregate.create_iterator()
    aggregate.first(iterator)
    
    while not aggregate.is_done(iterator):
        print(aggregate.current_item(iterator))
        aggregate.next(iterator)
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...