29

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

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

我猜另一种选择是返回 aNullCommand或其他东西,但最佳实践是什么?

4

4 回答 4

34

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

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

于 2012-06-20T17:04:59.253 回答
2

我同意乔恩·斯基特的观点。CreateCommand显然意味着建设。

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

于 2012-06-20T17:11:30.100 回答
2

在这种情况下返回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 ...
}
于 2012-06-20T17:19:41.793 回答
0

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

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

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

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

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

于 2012-06-20T17:20:27.903 回答