Java Supplier Interface y Patrón Factoría

Supplier interface

Supplier interface


En esta entrada de refactorizando, Java Supplier Interface y Patrón Factoría vamos a ver y entender un poco mejor el uso y la finalidad que hay con el uso de Java Supplier.

Esta interfaz funciona de manera similiar al Patrón Factory o Factoría por lo que vamos a empezar viendo este patrón.

¿Qué es el Patrón Factoría?

El patrón Factoría es uno de los más usados en el diseño y construcción de software y frameworks. En este patrón, creamos un objeto sin exponer la lógica de creación y nos refereimos al objeto nuevo mediante una interfaz común.

Patrón Factoría | Java Supplier Interface y Patrón Factoría
Patrón Factoría

Vamos a entenderlo mejor con un ejemplo, vamos a partir de una clase animal y a partir de esa clase tendremos dos clase perro y gato que implementaran la clase animal.

Ahora vamos a construir las 3 clases, siendo perro y gato dos clases que extenderán de la clase padre Animal. La idea es obtener el número de patas en función del animal.

package com.refactorizando.supplier;

public  abstract class Animal {

  public abstract int patas();

}
package com.refactorizando.supplier;

public class Perro extends Animal {

  private int patas;
  public Perro() {
    this(4);
  }
  public Perro(int patas) {
    super();
    this.patas = patas;
  }
  public int getPatas() {
    return patas;
  }
  public void setPatas(int patas) {
    this.patas = patas;
  }
  @Override
  public int patas() {
    return patas;
  }
}
package com.refactorizando.supplier;

public class Gato extends Animal {

  private int patas;
  public Gato() {
    this(4);
  }
  public Gato(int patas) {
    super();
    this.patas = patas;
  }
  public int getPatas() {
    return patas;
  }
  public void setPatas(int patas) {
    this.patas = patas;
  }
  @Override
  public int patas() {
    return patas;
  }
}
package com.refactorizando.supplier;

public class Avestruz extends Animal {

  private int patas;
  public Avestruz() {
    this(2);
  }
  public Avestruz(int patas) {
    super();
    this.patas = patas;
  }
  public int getPatas() {
    return patas;
  }
  public void setPatas(int patas) {
    this.patas = patas;
  }
  @Override
  public int patas() {
    return patas;
  }
}

Una vez hemos definido las tres clases vamos a ver como utilizar una u otra en función de lo que necesitamos:

package com.refactorizando.supplier;

public class FactoriaAnimales {

   public static Animal obtenerPatasAnimal(String tipo) {

      if (tipo.equalsIgnoreCase("Avestruz")) {
         return new Avestruz();
      }else if (tipo.equalsIgnoreCase("Perro")){
         return new Perro();
      } else {
         return new Gato();
      }
   }
}
package com.refactorizando.supplier;

public class Animales {
   public static void main(String[] args) {

      Animal animal=FactoriaAnimales.obtenerPatasAnimal("Avestruz");

      System.out.println(animal.patas());
   }
}

En este caso obtendríamos una salida de 2 ( el avestruz tiene dos patas). Ahora vamos a ver como lo haríamos haciendo uso de supplier.

Interfaz Java Supplier

La interfaz Java Supplier pertenece al paquete java.util.function y fue introducida en Java 8 para poder implementar programación funcional con Java. Representa una función a la cual no se le pasa ningún argumento y devuelve un valor genérico T.

Para utilizarlo se invoca al método get para producir un valor de la expresión lambda asignada a un objeto.

Vamos a ver su utilización partiendo del ejemplo anterior de nuestra Factoría Animal.

package com.refactorizando.supplier;

import java.util.HashMap;
import java.util.function.Supplier;

public class FactoriaSupplierAnimal {

   private static final String PERRO = "perro";
   private static final String GATO = "gato";
   private static final String AVESTRUZ = "avestruz";

   private static HashMap<String, Supplier<Animal>> animalMap= new HashMap<>();

   static {
      animalMap.put(AVESTRUZ, Avestruz::new);
      animalMap.put(PERRO, Perro::new);
      animalMap.put(GATO, Gato::new);
   }

   public static Animal getAnimal(String tipo) {

      if (animalMap.get(tipo)!=null) {

         return animalMap.get(tipo).get();

      }
      throw new IllegalArgumentException("Animal not found");

   }
}

Al igual que hacemos con el patrón factoría aquí, nos hemos apoyado en Supplier para tener una referencia a la creación del objeto por ejemplo, Avestruz::new. De esta forma podremos recuperar el objeto o incorporar más a la implementación.

Para incorporar el objeto a través de Supplier nos apoyamos en get(), tal y como hemos comentado antes, para producir un valor de la expresión lambda asignada.

Conclusión

En esta entrada sobre Java Supplier Interface y Patrón Factoría, hemos visto como funciona esta interfaz funcional y como y cuando implementarla. Aunque su uso no es de lo más extendido, quizás debido a falta de conocimiento sobre como usarlo, suele ser de gran utilidad dentro de las aplicaciones, sobre todo para eliminar el boilerplate que nos da aplicar el patrón factoría.

Si te interesan otros patrones de diseño puedes echar un ojo aquí.


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *