2012-06-20 3 views
26

Мне интересно узнать о лучшей практике здесь. Является ли хорошей практикой метод фабрики возвращать null, если он не может создать что-либо? Вот пример:Возможно ли, чтобы метод фабрики возвращал значение null?

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

Альтернативой было бы вернуть NullCommand или что-то, я думаю, но что лучше практика?

ответ

31

Я думаю, что потенциально разумно, чтобы фабричный метод возвращал значение null в некоторых ситуациях, но не, если это метод под названием CreateCommand. Если бы это было GetCommand или FetchCommand, это может быть хорошо ... но метод Create должен бросить исключение при неудаче, я бы предложил.

Действительно ли вы действительно хотите, чтобы он вернулся null в этой ситуации, в зависимости от большей картины, конечно. (Есть ли разумная реализация нулевого объекта, которую вы могли бы вернуть, например?)

+0

Согласен с @Jon Skeet. Create подразумевает конструктор, и вы не ожидаете ни одного из них, так что маловероятно, что вы проверите, чтобы убедиться, что это так. –

+0

@TonyHopkinson: С другой стороны, вы также не ожидали бы исключения из конструктора. –

+6

@TimSchmelter: Почему бы и нет? Я бы * абсолютно * ожидал исключения из конструкторов в определенных ситуациях - 'FileStream' был классическим примером ...или что-либо с параметрами, которые могут быть недействительными в любой форме, например. давая нулевую ссылку на что-то, ожидающее ненулевой ссылки. –

1

Я согласен с Джоном Скитом. CreateCommand ясно подразумевает строительство.

Если вы не выбрали Exception, то в этом случае я лично воспользовался бы реализацией NullCommand, чтобы избежать условных утверждений у всех потребителей и возможных ошибок NullReferenceException.

3

Возврат null в этом случае сделает ваш метод более сложным в использовании; клиенты должны знать о неявном состоянии отказа. Вместо этого, бросить исключение, и вы также можете предоставить отдельный метод для клиентов, чтобы проверить для этого условия:

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

Или сделать заводскую instantiatable; который был бы лучше, если вам нужно предварительно обработать 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 ... 
} 
+0

_ ", возможно, завершится с ошибкой, если они не проведут проверку нулевого значения. Поскольку C# не поддерживает проверенные исключения (в отличие от java), клиенты также могут потерпеть неудачу, если они не обрабатывают это исключение, поэтому это не сильный аргумент (imho) , –

+1

@TimSchmelter: Я пересмотрел свою формулировку на эту фразу .... Надеюсь, теперь мой взгляд станет яснее. –

0

Это имеет смысл только вернуть Null, если есть причина, почему вы хотите пользователю иметь для проверки нуль каждый раз, когда он называет Create. Как правило, вы бы рассмотреть следующие совершенно реально существующей модели использования:

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

Но что вы предлагаете, чтобы заставить следующую схему использования:

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

Обычно Null сценарий будет означать некоторые вид сбоя, и в этом случае исключение, вероятно, будет иметь наибольший смысл. Но в конечном итоге вы здесь создатель музыки и должны решить, что разумно в мире, который вы строите.

Смежные вопросы