【问题标题】:Is it OK for a factory method to return null?工厂方法返回 null 可以吗?
【发布时间】:2012-06-22 21:14:34
【问题描述】:

我想知道这里的最佳做法。如果工厂方法无法创建任何东西,则返回 null 是一种好习惯吗?这是一个例子:

ICommand command = CommandFactory.CreateCommand(args);
if (command != null)
    command.Execute();
else
    // do something else if there is no command

我猜另一种方法是返回NullCommand 或其他东西,但最佳做法是什么?

【问题讨论】:

    标签: c# oop design-patterns factory-method


    【解决方案1】:

    在这种情况下返回null 会使您的方法更难使用;客户必须意识到隐含的故障条件。相反,抛出异常,您还可以为客户端提供单独的方法来测试这种情况:

    if (CommandFactory.CanCreate(args)) {
      ICommand command = CommandFactory.Create(args);
      command.Execute();
    }
    

    或者使工厂可实例化;如果您需要预处理args,那会更好:

    CommandFactory factory = new CommandFactory(args);
    if (factory.IsValid()) {
      ICommand command = factory.Create();
      command.Execute();
    }
    

    工厂的接口现在清楚明确地表明创建可能会失败,但它仍然需要客户端使用检查方法。另一种选择是:

    ICommand command;
    if (CommandFactory.TryCreate(args, out command)) {
      // creation succeeded ...
    }
    

    【讨论】:

    • "如果不检查 null 可能会失败" 由于 C# 不支持检查异常(与 java 不同),如果客户端不处理也可能会失败那个例外,所以这不是一个强有力的论点(恕我直言)。
    • @TimSchmelter:我修改了那句话的措辞……希望我的观点现在更清楚了。
    【解决方案2】:

    只有在您希望用户每次调用 Create 时都必须检查 null 的原因时,才返回 Null 才有意义。通常,您会认为以下是完全有效的使用模式:

    var obj = MyFactory.CreateThing();
    obj.DoSomething();
    

    但您的建议是强制使用以下使用模式:

    var obj = MyFactory.CreateThing();
    if (obj == Null) {
        // Handle null condition
    } else {
        obj.DoSomething();
    }
    

    通常 Null 场景意味着某种失败,在这种情况下,异常可能最有意义。但最终你是这里的音乐制作者,你必须决定在你正在构建的世界中什么是明智的。

    【讨论】:

      【解决方案3】:

      我同意 Jon Skeet 的观点。 CreateCommand 显然意味着构造。

      如果您不抛出Exception,那么在这种情况下,我会亲自使用NullCommand 实现,以避免所有消费者中的条件语句和可能的NullReferenceException 错误。

      【讨论】:

        【解决方案4】:

        我认为工厂方法在某些情况下返回 null 可能是合理的,但不是如果它是一个名为 CreateCommand 的方法。如果是GetCommandFetchCommand,那可能没问题...但是我建议Create 方法在失败时应该抛出异常。

        您是否真的希望它在这种情况下返回null,当然,这取决于大局。 (例如,您可以返回一个合理的空对象实现吗?)

        【讨论】:

        • 同意@Jon Skeet。 Create 隐含构造函数,并且您不希望其中一个为 null,因此您不太可能检查它是否是这样做的。
        • @TonyHopkinson:另一方面,您也不希望构造函数出现异常。
        • @TimSchmelter:为什么不呢?我绝对希望在某些情况下构造函数会出现异常 - FileStream 是一个经典示例......或者任何带有可能以任何形式无效的参数的东西,例如对期望非空引用的事物提供空引用。
        • @JonSkeet:是的,在某些情况下,但这是一段流利的段落(正确的英文术语是什么?)。这是我缺少 java 的 throws 关键字以确保它由调用者处理的情况之一。
        • @TimSchmelter:即使在 Java 中,您也不会将它用于明显无效的参数之类的事情。基本上我不认为抛出异常的构造函数与抛出异常的方法特别不同,除了如果你分配了任何非托管资源需要更加小心(因为调用者将无法处理新构造的对象)。
        猜你喜欢
        • 1970-01-01
        • 2011-12-10
        • 1970-01-01
        • 2017-05-10
        • 2012-08-13
        • 2015-02-22
        • 1970-01-01
        • 2023-03-10
        相关资源
        最近更新 更多