Вы правы, если вы уверены, что никогда не возвращаете нули, просто пропустите проверку на ноль перед вызовом метода в первой реализации. Аналогичным образом, если вам нужно сделать что-то особенное в случае, если UseA()
нужно сделать что-то по-другому для нулевого объекта, вам все равно нужно явно проверить наличие нулевого объекта. Однако, в чем действительно помогает шаблон с нулевым объектом, так это в тех ситуациях, когда он не имеет значения.
Взять, к примеру, большинство шаблонов наблюдателей. Если вы реализуете свой шаблон наблюдателя как член вашего класса, для которого может быть только один наблюдатель, и хотите сообщить наблюдателю, что ваш класс что-то сделал, для класса не имеет значения, является ли наблюдатель нулевым или нет.
Это также иллюстрируется классами пустых контейнеров, которые по сути являются шаблоном нулевого объекта: вместо возврата пустого контейнера из запроса вы просто возвращаете пустой контейнер. Для таких вещей, как итерация по всем элементам контейнера, часто не имеет значения, пуст он или нет, поэтому избавление от необходимости нулевой проверки делает код более понятным и более читабельным. Однако, если вы хотите заполнить представление своего набора данных, вам все равно нужно явно показать другое «Нет записей». который проверяет пустой контейнер.
Изменить для ясности
Одна проблема - смотреть только на сайте вызовов. Как и большинство шаблонов проектирования, это должно охватывать обе стороны, чтобы быть полностью использованы. Рассмотрим:
public PossiblyNull GetSomethingNull()
{
if (someBadSituation())
return null;
else
return SomehowProduceSomething();
}
против
public PossiblyEmpty GetSomethingEmpty()
{
if (someBadSituation())
return StaticEmptySomething();
else
return ProdueSomethingYay();
}
Теперь ваш код звонка вместо того, чтобы выглядеть как
public void DoSomethingWithChild(Foo foo)
{
if (foo != null)
{
PossiblyNull bar = foo.GetSomething();
if (bar != null)
bar.DoSomething();
}
}
это может быть
public void DoSomethingWithChild(Foo foo)
{
if (foo != null)
foo.GetSomething().DoSomething();
}