Построить итератор - PullRequest
       27

Построить итератор

0 голосов
/ 09 января 2010

Допустим, вы хотите создать итератор, который выплевывает объекты File. Какой тип данных вы обычно предоставляете конструктору такого итератора?

  • массив предварительно созданных объектов File или
  • просто необработанные данные (например, многомерный массив), и позволяет итератору создавать объекты File на лету при выполнении итерации через?

Edit:
Хотя мой вопрос на самом деле был как можно более общим, мне кажется, что мой пример слишком широк для общего понимания, поэтому я уточню немного подробнее. Объекты File, о которых я говорю, на самом деле являются ссылками на файлы из базы данных. Смотрите эти две таблицы:

folder
| id | folderId | name             |
------------------------------------
|  1 |     null | downloads        |

file
| id | folderId | name             |
------------------------------------
|  1 |        1 | instructions.pdf |

Они ссылаются на фактические папки и файлы в файловой системе.

Теперь я создал объект FileManager. Это сможет вернуть список папок и файлов. Например:

FileManager::listFiles( Folder $folder );

... вернул бы итератор объектов File (или, если подумать, скорее объекты FileReference) из базы данных.

Итак, мой вопрос сводится к следующему: Если объект FileManager создает Iterator в listFiles (), вы должны сделать что-то вроде этого (псевдокод):

listFiles( Folder $folder )
{
    // let's assume the following returns an multidimensional array of rows
    $filesData = $db->fetch( $sqlForFetchingFilesFromFolder );
    // let the Iterator take care of constructing the FileReference objects with each iteration
    return FileIterator( $filesData );

}

или (псевдокод):

listFiles( Folder $folder )
{
    // let's assume the following returns an multidimensional array of rows
    $filesData = $db->fetch( $sqlForFetchingFilesFromFolder );
    $files = array();
    for each( $filesData as $fileData )
    {
        $files.push ( new FileReference( $fileData ) );
    }
    // provide the Iterator with precomposed FileReference objects
    return FileIterator( $files );

}

Надеюсь, это немного прояснит ситуацию.

Ответы [ 4 ]

1 голос
/ 09 января 2010

Мне кажется, что вопрос неясен.

Мы говорим об Итераторе или Фабрике?

Для меня Iterator работает с уже существующей коллекцией вещей и позволяет вызывающей стороне работать с каждой вещью по очереди.

Когда вы говорите «Выполняет», вы имеете в виду, что позволяет клиенту работать с одним файлом из существующего набора файлов, или вы имеете в виду, что вы выполняете итерацию некоторых данных и намереваетесь сохранить эти данные в файлах, которые вы генерируете , Если мы генерируем, то у нас есть Файловая фабрика.

Я предполагаю, что вы собираетесь обрабатывать некоторые файлы в файловой системе. Я думаю, что ваш итератор похож на каталог, он может дать вам следующий файл, о котором он знает. Поэтому я создаю «Driectory», передавая достаточно данных, чтобы позволить ей знать, какие файлы вы имеете в виду (это может быть просто путь к ОС, может быть какое-то выражение «find», список ссылок, подобных ftp и т. Д.) И ожидайте, что это даст мне следующий Файл, когда я буду повторяться.

---- обновлено после уточнения вопроса

Я думаю, что ключевой вопрос здесь - когда нужно открывать отдельные файлы. Сам итератор будет разумно возвращать объект File, соответствующий дескриптору открытого файла, после чего вызывающая программа может просто работать с файлом. Но обычно, если итератор работает с списком предварительно открытых файлов или списком ссылок на файлы, файлы открываются как итератор next ().

Я думаю, что мы должны сделать последнее, потому что есть открытый доступ к открытому файлу, поэтому мы должны открывать файлы только тогда, когда они нам нужны.

Это приводит к еще одному моменту: кто закрывает файл? Мы не можем позволить себе держать их всех открытыми. Возможно, итератор должен закрыть каждый файл при вызове next (). Это означает, что сам итератор нуждается в методе close (), чтобы привести в порядок текущий открытый файл. В качестве альтернативы нам необходимо четко документировать, что закрытие является обязанностью клиента.

1 голос
/ 09 января 2010

Каким должен быть ваш объект «Файл»? Открытый дескриптор файла или представление пути к файловой системе, которое можно открыть по очереди?

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

Ваши требования не ясны, если честно - по моему опыту, большинство итераторов, которые выдают серию файлов, используют что-то вроде Directory.GetFiles(pattern) - вы не передаете им необработанные данные вообще, вы передаете им что-то, что они могут использовать, чтобы найти данные для вас .

Непонятно, к чему вы стремитесь - такое чувство, что вы пытаетесь задать общий вопрос, но вы не предоставили достаточно информации, чтобы мы могли вас проконсультировать. Это все равно что спросить: «Хочу ли я использовать строку или целое число?» без указания контекста.

РЕДАКТИРОВАТЬ: Я бы, вероятно, подтолкнул все этой логики в FileIterator, лично. В противном случае трудно понять, какую ценность это действительно дает. В таких языках, как C # или Python, вам не понадобился бы отдельный класс, во-первых, вы просто использовали бы генератор некоторого описания. В этом смысле этот вопрос не зависит от языка: (

1 голос
/ 09 января 2010

Что именно должен делать ваш итератор? Записать данные в файлы? Создать их?

Итератор - это шаблон для итерации через данные, что означает предоставление последовательных данных единообразным способом, а не изменение их.

0 голосов
/ 09 января 2010

Зависит от того, что вам нужно. Например, вы могли бы иметь:

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

Вы можете создать базовый класс, например, FilenameCollection или Directory, у которого есть метод, который возвращает соответствующий итератор для объекта этого типа (то есть итератор "фабричный метод"), вместо того, чтобы требовать передачи параметра в конструктор вашего итератора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...