【问题标题】:Construct an Iterator构造一个迭代器
【发布时间】:2010-01-09 10:17:48
【问题描述】:

假设您要构造一个输出 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() 中构造迭代器,你会做这样的事情吗(伪代码):

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 );

}

希望这能澄清一点。

【问题讨论】:

    标签: language-agnostic oop iterator


    【解决方案1】:

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

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

    说实话,您的要求并不清楚 - 根据我的经验,大多数产生一系列文件的迭代器都使用类似 Directory.GetFiles(pattern) 的东西 - 你根本不向他们传递原始数据,你传递给他们一些东西他们可以使用为您查找数据

    您想要了解的内容并不明显 - 感觉就像您在尝试提出一般性问题,但您没有提供足够的信息来让我们为您提供建议。这就像在问,“我要使用字符串还是整数?”没有给出任何上下文。

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

    【讨论】:

    • File 对象实际上是用来表示文件系统路径的。您说得对,一次打开所有物理文件是个坏主意。那确实不是我的本意。我已经更新了我的问题。请参阅我的扩展问题以获取更多信息。谢谢。
    【解决方案2】:

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

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

    【讨论】:

    • 我已经更新了我的问题。请参阅我的扩展问题以获取更多信息。谢谢。
    【解决方案3】:

    我觉得这个问题不清楚。

    我们说的是迭代器还是工厂?

    对我来说,迭代器正在对预先存在的 事物 集合进行操作,并允许调用者依次处理每个 事物

    当您说“Spits Out”时,您的意思是允许客户端使用预先存在的一组文件中的一个文件,还是您的意思是您正在迭代一些数据并打算将该数据存储在您正在生成的文件中.如果我们正在生成,那么我们就有了一个文件工厂。

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

    ----更新以下问题说明

    我认为这里的关键问题是何时应该打开各个文件。 Iterator 本身将合理地返回一个与打开的文件句柄相对应的 File 对象,然后调用者可以直接使用该文件。但是迭代器通常应该针对预先打开的文件的 list 或文件引用的 list 工作,使用作为迭代器 next() 打开的文件。

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

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

    【讨论】:

    • 嗯,你说得很好,说目录本身可以是迭代器。没有这么想过。谢谢!
    • 尽管您提出了正确的观点,但我关心的并不是打开实际的物理文件。 Iterator 起初只是为了在 MVC 应用程序的视图中显示文件的名称。稍后,我希望 File(Reference) 对象为我提供实际的物理文件以供下载。但这还不是我关心的问题。我更关心的是如何生成迭代器。但既然你对迭代器给出了完全不同的看法,我想我会重新考虑我的设计。我喜欢您的“让目录本身充当迭代器”的想法。
    猜你喜欢
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2021-01-15
    • 2021-01-19
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多