Паттерн «Нулевой объект»

В паттерне Null Object null-объект заменяет проверку экземпляров объекта на NULL. Вместо проверки значений на null Null-объект отвечает отношением, которое ничего не делает. Такой Null-объект также может обеспечивать поведение по умолчанию, когда данные недоступны.

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


summary

назначение

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

Основные решаемые проблемы

  • Паттерн Null Object решает проблемы, которые могут возникнуть при использовании значений null в системе, такие как исключения NullPointerException.
  • Это позволяет системе продолжать работу с "безопасным" null-объектом, когда нет подходящего объекта, вместо отказа.

Сценарий использования

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

Подход к реализации

  • Определите протокол:Определите протокол или интерфейс, который задает поведение, которое должно быть реализовано.
  • Создание конкретных объектов:Конкретные объекты, которые реализуют протокол и обеспечивают реальное поведение.
  • Создайте null-объект:Также реализуйте тот же протокол, но предоставьте "пустую" реализацию, то есть никакие значимые операции не выполняются.

Ключевой код

  • Протокол или интерфейс:Задает методы, которые объект должен реализовать.
  • Конкретный объект:Реализует протокол и содержит реальную бизнес-логику.
  • Null-объект:Реализует протокол, но реализации методов пусты или представляют собой поведение по умолчанию.

Пример приложения

  • Система логирования:В системе логирования null-объект может представлять логгер, который не выполняет никаких операций.
  • Пользователь по умолчанию:В системе, если в данный момент нет пользователя, вместо null можно использовать пустой объект пользователя.

Преимущества

  1. Избегание проверок на null:Устраняет проверки на null в коде.
  2. Упрощение клиентского кода:Клиенты могут напрямую вызывать методы независимо от того, является ли объект null.
  3. Расширяемость:Добавление новых конкретных объектов прозрачно для клиентов и не требует изменения существующего кода.

Недостатки

  • Может скрывать ошибки:Использование null-объектов может скрывать ошибки или исключительные ситуации, что затрудняет отладку.
  • Увеличивает сложность проектирования:Null-объект нужно реализовать для каждого интерфейса, который может возвращать null.

Рекомендации по использованию

  • Когда системе нужно обрабатывать значения null, но также хочется упростить обработку ошибок и избежать проверок на null, стоит рассмотреть использование паттерна Null Object.

Примечания

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

Структура

Паттерн Null Object включает следующие основные роли:

  • AbstractionObject(Абстрактный объект):Определяет интерфейс, ожидаемый клиентом. Этот интерфейс может быть абстрактным классом или интерфейсом.

  • Concrete Object(Конкретный объект):Конкретные классы, реализующие интерфейс абстрактного объекта. Эти классы предоставляют реальное поведение.

  • Нулевой объект:Класс нулевого объекта, который реализует интерфейс абстрактного объекта. Этот класс предоставляет поведение по умолчанию, не выполняющее никаких действий, которое используется, когда объект недоступен или неприменим. Он может служить заменой конкретным объектам, заменяя проверки на null в клиентском коде.

Реализация

Мы создадим класс, который определяет операции (здесь — имя клиента) ...AbstractCustomerАбстрактный класс, и расширяющиеAbstractCustomerклассы сущностей этого класса. Фабричный классCustomerFactoryНа основании имени, переданного клиентом, вернутьRealCustomerилиNullCustomerобъект.

NullPatternDemo, наш демонстрационный класс используетCustomerFactoryдля демонстрации использования паттерна Нулевой объект.

空对象模式的 UML 图

Шаг 1

Создайте абстрактный класс.

AbstractCustomer.java

public abstract class AbstractCustomer { protected String name; public abstract boolean isNil(); public abstract String getName(); }

Шаг 2

Создайте классы сущностей, расширяющие вышеуказанный класс.

RealCustomer.java

public class RealCustomer extends AbstractCustomer { public RealCustomer(String name) { this.name = name; } @Override public String getName() { return name; } @Override public boolean isNil() { return false; } }

NullCustomer.java

public class NullCustomer extends AbstractCustomer { @Override public String getName() { return "Недоступно в базе данных клиентов"; } @Override public boolean isNil() { return истина; } }

Шаг 3

СоздатьCustomerFactoryкласс.

CustomerFactory.java

public class CustomerFactory { public static final String[] names = {"Rob", "Joe", "Julie"}; public static AbstractCustomer getCustomer(String name){ for (int i = 0; i < names.length; i++) { if (names[i].equalsIgnoreCase(name)){ return new RealCustomer(name); } } return new NullCustomer(); } }

Шаг 4

ИспользованиеCustomerFactory, в зависимости от имени, переданного клиентом, для полученияRealCustomerилиNullCustomerОбъект.

NullPatternDemo.java

public class NullPatternDemo { public static void main(String[] args) { AbstractCustomer customer1 = CustomerFactory.getCustomer("Роб"); AbstractCustomer customer2 = CustomerFactory.getCustomer("Боб"); AbstractCustomer customer3 = CustomerFactory.getCustomer("Джули"); AbstractCustomer customer4 = CustomerFactory.getCustomer("Лаура"); System.out.println("Клиенты"); System.out.println(customer1.getName()); System.out.println(customer2.getName()); System.out.println(customer3.getName()); System.out.println(customer4.getName()); } }

Шаг 5

Запустите программу, вывод результата:

Customers
Rob
Not Available in Customer Database
Julie
Not Available in Customer Database
Другие расширения