Нулевой объектный образец Фаулера: зачем использовать наследование? - PullRequest
4 голосов
/ 10 ноября 2009

Почему Фаулер PoEAA с. 498 определяют шаблон нулевого объекта следующим образом (образец сокращен, язык c #, но это не имеет значения):

public class Customer
{
  public virtual string Name {get; set;}
}

public class NullCustomer : Customer, INull
{
  public override Name 
  {
     get { return "ImTheNull";}
     // setter ommitted
  }
}

INull используется в качестве интерфейса маркера. Мне не очень нравится этот подход по трем причинам:

  1. Свойства должны быть помечены как виртуальные
  2. Я больше не могу запечатать свои классы сущностей
  3. По крайней мере (n + 1) введены новые типы (n пустых объектов, один интерфейс маркера)

Почему это не реализовано так:

public class Customer
{
  public static readonly Customer NullCustomer = new Customer(){Name = "ImtTheNullCustomer";}

  public string Name {get; set;}
}

Я, как правило, нашел все примеры Фаулера хорошо продуманными, и, должно быть, я кое-что здесь упустил.

Ответы [ 4 ]

10 голосов
/ 10 ноября 2009

Причиной наследования является переопределение поведения класса. То, как вы об этом думаете, мне кажется, что вы собираетесь проверить, равен ли ваш объект статическому экземпляру NullCustomer, чтобы принять решение, однако цель нулевого объекта - поддержать Лискова. принцип замещения .

Другими словами, вы используете нулевой объект для установки ссылки, и у вас не будет специальной проверки для него, вы просто будете использовать его, и у него должно быть другое поведение (на самом деле отсутствие поведения).

1 голос
/ 10 ноября 2009

Проблема вашего второго примера с магическим значением состоит в том, что если в вашем классе есть другие предметы, которые являются частью класса, теперь вам нужно вставить проверки против магии, чтобы принять решение о возвращении информации или какой-либо другой соответствующей информации .

С классом Null класс возвращает то, что наиболее целесообразно, без таких проверок.

Например, класс клиента может вернуть общие долларовые расходы этого пользователя после соответствующего запроса к БД. NullCustomer мог бы просто return 0;. С магическим значением он либо получит информацию для фиктивного пользователя из БД, либо должен будет выполнить другую конкретную проверку, прежде чем делать разумную вещь.

0 голосов
/ 10 ноября 2009

Я не программист на C #, но во втором примере похоже, что вы могли бы сделать эквивалент:

Customer.NullCustomer.Name = "Not Null";

Как правило, объекты имеют поведение, а не только данные, поэтому все становится сложнее.

0 голосов
/ 10 ноября 2009

Добавление к тому, что сказал Чеп. Шаблон Null Object используется для того, чтобы по умолчанию был допустимый набор значений. Кроме того, если вы попытаетесь использовать NullCustomer в MVC, вы все равно сможете получить доступ к объекту, представляющему модель, вместо того, чтобы учитывать потенциальные несуществующие данные. [проверка на нули]

...