Логотип ConstructiCat
CodeBust.
Навигация по разделу ▾

Введение Null-объекта.

Проблема

Из-за того, что некоторые методы возвращают null вместо реальных объектов, у вас в коде присутствует множество проверок на null.

Решение

Вместо null возвращайте Null-объект, который предоставляет поведение по умолчанию.

##Пример

До
if (customer == null) {
  plan = BillingPlan.basic();
}
else {
  plan = customer.getPlan();
}
После
class NullCustomer extends Customer {
  boolean isNull() {
    return true;
  }
  Plan getPlan() {
    return BillingPlan.basic();
  }
  // Прочее поведение Null-объекта.
}

// Замена значений null на Null-объект.
customer = (order.customer != null) ?
  order.customer : new NullCustomer();

// Null-объект используется так же, как обычный подкласс.
plan = customer.getPlan();

##Зачем делать рефакторинг

Десятки проверок на null усложняют и засоряют код.

##Как делать рефакторинг

  1. Из интересующего вас класса создайте подкласс, который будет выполнять роль Null-объекта.

  2. В обоих классах создайте метод isNull(), который будет возвращать true для Null-объекта и false для реального класса.

  3. Найдите все места, где код может вернуть null вместо реального объекта. Измените этот код так, чтобы он возвращал Null-объект.

  4. Найдите все места, где переменные реального класса сравниваются с null. Замените такие проверки вызовом метода isNull().

  5. Теперь упростите сами условные операторы:

    • Если в этих условных операторах при значении не равном null выполняются методы исходного класса, переопределите эти методы в Null-классе и вставьте туда код из else части условия. После этого условный оператор можно будет вообще удалить, а разное поведение будет осуществляться за счёт полиморфизма.
    • Если не все так просто, и методы переопределить не получается, посмотрите, нельзя ли просто вынести операции, которые должны были выполняться при значении, равном null, в новые методы Null-объекта. Вызывайте эти методы вместо старого кода в else как операции по умолчанию.