构造一个迭代器

时间:2010-01-09 10:17:49

标签: language-agnostic oop iterator

假设您要构造一个吐出File对象的Iterator。您通常为这种迭代器的构造函数提供什么类型的数据?

  • 预构建的File对象数组,或
  • 只是原始数据(例如多维数组),让Iterator在迭代时动态创建File对象?

修改
虽然我的问题实际上是一般可能的,但似乎我的例子有点广泛来解决一般情况,所以我会详细说明一下。我正在谈论的File对象实际上是来自数据库的文件引用。见这两个表:

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

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

它们引用文件系统上的实际文件夹和文件。

现在,我创建了一个FileManager对象。这将能够返回文件夹和文件的列表。例如:

FileManager::listFiles( Folder $folder );

...将从数据库中返回File对象的迭代器(或者,从而考虑它,而不是FileReference对象)。

所以我的问题归结为: 如果FileManager对象在listFiles()中构造Iterator,你会做这样的事情(伪代码):

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 个答案:

答案 0 :(得分:1)

你的迭代器到底应该做什么?将数据写入文件?创建它们?

迭代器是迭代数据的模式,这意味着以统一的方式提供顺序数据,而不是改变它们。

答案 1 :(得分:1)

你的“文件”对象是什么意思?文件的打开句柄,还是可以依次打开的文件系统路径的表示形式?

一次打开​​所有文件通常是个坏主意 - 毕竟,使用迭代器的一部分原因是你一次只能访问一个对象。你的迭代器一次可以产生一个打开的文件,让调用者负责关闭它,尽管再次使用可能有点奇怪。

您的要求不明确,说实话 - 根据我的经验,产生一系列文件的大多数迭代器都使用类似Directory.GetFiles(pattern)的东西 - 您根本不传递原始数据,而是传递它们他们可以用来为您找到的数据

你想要达到的目标并不明显 - 感觉就像是在试图提出一般性问题,但是你没有提供足够的信息让我们为你提供建议。这就像问:“我想使用字符串还是整数?”没有任何背景。

编辑:我个人可能会将所有的逻辑推送到FileIterator。否则,很难看出它真正提供的价值。在像C#或Python这样的语言中,您首先不需要单独的类 - 您只需使用某些描述的生成器。在这个意义上,这个问题不是语言不可知的:(

答案 2 :(得分:1)

我发现问题不明确。

我们在谈论Iterator还是Factory?

对我来说,Iterator正在运行一个已经存在的事物集合,并允许调用者依次处理每个事物

当您说“吐出”时,您的意思是允许客户端使用预先存在的一组文件中的一个文件,或者您是否意味着您正在迭代某些数据并打算将这些数据存储在您正在创建的文件中。如果我们正在创建,那么我们就有了一个文件工厂。

我的猜测是你打算在sytstem文件中处理一些文件。我认为你的迭代器类似于一个目录,它可以为你提供它所知道的下一个文件。因此,我通过传递足够的数据来构建“Driectory”,以便让它知道你的意思是哪些文件(可能只是一个OS路径,可能是某种“查找”文件,类似ftp的引用列表等)和期待它在迭代时给我下一个文件。

----在问题澄清后更新

我认为这里的关键问题是应该打开单个文件。 Iterator本身将合理地返回对应于打开文件句柄的File对象,然后调用者可以使用该文件。但理所当然,迭代器应该对预打开文件的列表或文件引用的列表进行操作,使用迭代器next()时打开文件。 / p>

我认为我们应该做后者,因为打开文件会有开销,因此我们应该只在需要时打开文件。

这导致了另外一点:谁关闭了文件?我们不能让他们全都开放。也许迭代器应该在调用next()时关闭每个文件。这意味着迭代器本身需要一个close()方法来允许整理当前打开的文件。 Alterntaivelywe需要明确记录关闭是客户的责任。

答案 3 :(得分:0)

这取决于你的需要。例如,您可以:

  • 要迭代的文件名的集合/列表;
  • 您要通过其迭代的目录的名称;
  • 你的迭代器可以自己决定要返回的文件;
  • ...

你可以设计一个基础类,例如FilenameCollectionDirectory有一个方法,为这种类型的对象返回一个适当的迭代器(即迭代器“工厂方法”),而不是要求将参数传递给迭代器的构造函数。