Patrón de objeto nulo

En el patrón de objeto nulo (Null Object Pattern), un objeto nulo reemplaza la verificación de instancias de objetos NULL. El objeto Null no consiste en comprobar valores nulos, sino en reflejar una relación que no realiza ninguna acción. Dicho objeto Null también puede proporcionar un comportamiento predeterminado cuando los datos no están disponibles.

En el patrón de objeto nulo, creamos una clase abstracta que especifica varias operaciones a realizar y una clase de entidad que extiende dicha clase; también creamos una clase de objeto nulo que no implementa nada de esa clase. Dicha clase de objeto nulo se utilizará sin problemas en los lugares donde se necesite verificar valores nulos.


Resumen

Intención

Usar un objeto nulo en lugar de un valor null. Este objeto nulo implementa la misma interfaz, pero no realiza ninguna operación o proporciona operaciones predeterminadas ante las solicitudes.

Problemas principales que resuelve

  • El patrón de objeto nulo resuelve los problemas que puede causar el uso de valores null en el sistema, como la excepción NullPointerException.
  • Permite que el sistema continúe ejecutándose con un objeto nulo "seguro" cuando no hay un objeto adecuado, en lugar de fallar.

Escenarios de uso

  • Cuando el sistema necesite manejar objetos null, pero se desee evitar las comprobaciones de null o el manejo de valores null.

Forma de implementación

  • Definir el protocolo: Definir un protocolo o interfaz que especifique los comportamientos que deben implementarse.
  • Crear el objeto concreto: El objeto concreto que implementa el protocolo y proporciona el comportamiento real.
  • Crear el objeto nulo: También implementa el mismo protocolo, pero proporciona una implementación "vacía", es decir, no ejecuta ninguna operación significativa.

Código clave

  • Protocolo o interfaz: Especifica los métodos que el objeto necesita implementar.
  • Objeto concreto: Implementa el protocolo y contiene la lógica de negocio real.
  • Objeto nulo: Implementa el protocolo, pero la implementación de los métodos está vacía o es un comportamiento predeterminado.

Ejemplos de aplicación

  • Sistema de logs: En el sistema de logs, un objeto nulo puede representar un registrador que no realiza ninguna operación.
  • Usuario predeterminado: En un sistema, si no hay un usuario actual, se puede usar un objeto de usuario nulo en lugar de null.

Ventajas

  1. Evitar la verificación de valores nulos: Elimina las comprobaciones de valores null en el código.
  2. Simplificar el código del cliente: El cliente puede ignorar si el objeto es nulo y llamar a los métodos directamente.
  3. Extensibilidad: Agregar nuevos objetos concretos es transparente para el cliente, sin necesidad de modificar el código existente.

Desventajas

  • Puede ocultar errores: El uso del objeto nulo puede ocultar errores o condiciones anómalas, lo que dificulta la depuración.
  • Aumenta la complejidad del diseño: Es necesario implementar un objeto nulo para cada interfaz que pueda devolver null.

Recomendaciones de uso

  • Cuando el sistema necesite manejar valores null, pero se desee simplificar el manejo de errores y evitar las comprobaciones de null, considere usar el patrón de objeto nulo.

Notas importantes

  • El patrón de objeto nulo debe usarse con precaución, asegurándose de que no enmascare errores ni oculte el estado real del sistema.
  • El objeto nulo debe proporcionar la misma interfaz que el objeto concreto, de modo que el código del cliente pueda usarlo sin necesidad de cambios.

Estructura

El patrón de objeto nulo incluye los siguientes roles principales:

  • Objeto abstracto (Abstract Object): Define la interfaz que el cliente espera. Esta interfaz puede ser una clase abstracta o una interfaz.

  • Objeto concreto (Concrete Object): Clases concretas que implementan la interfaz del objeto abstracto. Estas clases proporcionan el comportamiento real.

  • Objeto nulo (Null Object): Clase de objeto nulo que implementa la interfaz del objeto abstracto. Esta clase proporciona un comportamiento inerte predeterminado, para usarse cuando el objeto no está disponible o no es accesible. Puede servir como sustituto del objeto concreto, reemplazando la verificación de valores nulos en el código del cliente.

Implementación

Vamos a crear una [clase] que defina la operación (aquí, el nombre del cliente)AbstractCustomerclase abstracta, y las clases de entidad que extienden laAbstractCustomerclase. La clase de fábricaCustomerFactorydevuelve, basándose en el nombre proporcionado por el cliente,RealCustomeroNullCustomerobjetos.

NullPatternDemo, nuestra clase de demostración usaCustomerFactorypara demostrar el uso del patrón de objeto nulo.

空对象模式的 UML 图

Paso 1

Crear una clase abstracta.

AbstractCustomer.java

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

Paso 2

Crear clases de entidad que extiendan la clase anterior.

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 "Not Available in Customer Database"; } @Override public boolean isNil() { return true; } }

Paso 3

Crear laCustomerFactoryclase.

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(); } }

Paso 4

UsarCustomerFactory, basándose en el nombre proporcionado por el cliente, para obtener losRealCustomeroNullCustomerobjetos.

NullPatternDemo.java

public class NullPatternDemo { public static void main(String[] args) { AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob"); AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob"); AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie"); AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura"); System.out.println("Customers"); System.out.println(customer1.getName()); System.out.println(customer2.getName()); System.out.println(customer3.getName()); System.out.println(customer4.getName()); } }

Paso 5

Ejecutar el programa y mostrar el resultado:

Customers
Rob
Not Available in Customer Database
Julie
Not Available in Customer Database
Otras extensiones