1

假设您有一个创建/复制/移动文件的功能。[逻辑]

对于应该复制/创建的文件已经存在的情况,您想询问用户是否覆盖该文件。[(G)UI]

如果(G)UI 和逻辑完全分离,你的实现方法是什么?

我首先想到的是 MVC 模式,但这意味着我必须在需要用户交互的任何地方使用它。

还有其他建议吗?

顺便说一句:您将如何在非 OO 语言中实现这一点?

4

6 回答 6

1

如果 GUI 和逻辑真的分开了,那么这个问题就不应该出现。根据设计,程序应根据具有默认值的选项覆盖或不覆盖。如果 GUI 可用,则可以设置该选项。

事实上,虽然显而易见的方法是直接开始复制,但您可以先通过查找冲突,并检查目标设备是否有足够的可用存储空间。然后,如果出现问题,什么也不做,除非有 GUI,在这种情况下,您可以报告问题并询问是否继续。

如果您想要一个可以逐个文件调用 GUI 的设计,那么将围绕它的逻辑设计为一组 n 个进程,每个进程复制一个文件,并在错误报告中提供可选的 GUI部分。GUI 然后可以重新调用复制一个文件的逻辑。

于 2009-10-23T14:22:49.970 回答
0

这种方法[伪代码]怎么样:

UIClass
{
    //
    // Some code
    //

    bool fileCopied = false;

    do {
        try {
            fileCopied = CopyFile(fileName);
        } catch (FileExists) {
            //
            // Ask "File exists! Overwrite?" If "No", exit do-loop
            //
        } catch (FileLocked) {
            //
            // Ask "File Locked! Repeat?",   If "No", exit do-loop
           //
        } catch (etc...) {
            //
            // etc.
            //    
        }
    } while (!fileCopied);

    //
    // Some code
    //
}

LogicClass
{
    //
    // Some code
    //

    bool CopyFile(string fileName)
    {
        //
        // copy file
        //
    }

    //
    // Some code
    //

}
于 2009-11-03T10:31:20.347 回答
0

我首先想到的是 MVC 模式,但这意味着我必须在需要用户交互的任何地方使用它。

这是一件坏事,为什么?分离 GUI 和逻辑正是MVC 模式的用途。不要仅仅因为它有一个长名称而害怕它——一旦你将 GUI 和逻辑分开,你就有了一个“视图”和一个“控制器”,至少,如果不是一个“模型”的话——如果你的应用程序有状态,你也有一个模型。你可能还没有对自己承认这一点。

于 2009-10-22T11:43:14.053 回答
0

在我看来,确实存在两个问题:

  1. 我们有一个算法(逻辑),我们希望将一些操作和决策推迟到其他东西(例如用户通过 UI)。
  2. 我们希望避免算法与其他事物之间的紧密耦合。

如果我们使用 OO 语言,有几种设计模式可以解决这两个特定问题。

  • 模板方法模式可以解决#1。它不能很好地解决#2,因为典型的实现是通过继承。
  • 观察者模式看起来也很有希望。

因此,实际上它是根据需要选择和混合最简单且最适合该语言的一种。

实际上,如果以 C# 为例,我们可以像这样实现 Template Method 和 Observer 混合:

// This will handle extensions to the FileCopy algorithm
abstract class FileCopyExtention
{
 public abstract Response WhatToDoWhenFileExists();
}


// the copy function, pure logic
public static void Copy(string source, string destination, FileCopyExtention extension) 
{
 if (File.Exists(destination))
 {
  var response = _extension.WhatToDoWhenFileExists();
  if (response == overwrite)
   // overwrite the file
  else
   // error
 }
}

// This is our user-interactive UI extension
class FileCopyUI : FileCopyExtention
{
 public override Response WhatToDoWhenFileExists()
 {
  // show some UI, return user's response to the caller
 }
}

// the program itself
void Main()
{
 Copy("/tmp/foo", "/tmp/bar", new FileCopyUI());
}

作为主题的变体,您可以使用事件、代表或您选择的任何语言提供。

在 C 中,这可能是一个函数指针,在 C++ 中,我猜是对一个类的引用。

于 2009-10-22T13:03:02.023 回答
0

我可以看到两种方式:

  • 你有两个功能,file_exists(...)copy_file(...)。UI 端总是file_exists先调用并询问用户是否复制文件是否已经存在。
  • 您只有一个功能copy_file(bool force, ...),如果文件存在,默认情况下会失败。所以 UI 端调用默认版本的函数,检查是否失败,原因是什么,如果是因为文件已经存在,询问用户并使用force=true.
于 2009-10-21T09:11:34.703 回答
0

在非 OO 语言中,我将实现某种事件队列,其中父(或子,取决于您的设计)UI 在“忙碌”标志为真时轮询事件。这样的事件让对方在等待“他们回答”标志成真时做其他工作。当然,必须观察两个方向的一些超时以及互斥。基本上,这里暗示了非阻塞 I/O 的原则或你最喜欢的关于实际无锁编程的理论。

有一定程度的分离..进程可以通信。根据您选择的语言,您可以通过具有原始信号的关系 DB 共享内存段、信号量 .. 或 IPC。对于这样一个笼统的问题,很难说得更具体。

请参阅我的评论,需要更多信息,以便可以制作出适用于您选择的语言的答案。

于 2009-10-21T09:14:37.120 回答