En los últimos meses, me topé algunas veces con la siguiente técnica / patrón. Sin embargo, parece que no puedo encontrar un nombre específico, ni estoy 100% seguro de todas sus ventajas y desventajas.
El patrón es el siguiente:
Dentro de una interfaz Java, un conjunto de métodos comunes se define como de costumbre. Sin embargo, al usar una clase interna, se filtra una instancia predeterminada a través de la interfaz.
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static Vehicle getInstance() {
return new Car(); // or use Spring to retrieve an instance
}
}
}
Para mí, parece que la mayor ventaja radica en el hecho de que un desarrollador solo necesita saber acerca de la interfaz y no de sus implementaciones, por ejemplo, en caso de que quiera crear rápidamente una instancia.
Vehicle someVehicle = Vehicle.Default.getInstance();
someVehicle.accelerate();
Además, he visto que esta técnica se usa junto con Spring para proporcionar dinámicamente instancias dependiendo de la configuración. En este sentido, también parece que esto puede ayudar con la modularización.
Sin embargo, no puedo evitar la sensación de que se trata de un mal uso de la interfaz, ya que combina la interfaz con una de sus implementaciones. (Principio de inversión de dependencia, etc.) ¿Podría alguien explicarme cómo se llama esta técnica, así como sus ventajas y desventajas?
Actualizar:
Después de un tiempo de consideración, volví a comprobar y noté que la siguiente versión singleton del patrón se usaba con mucha más frecuencia. En esta versión, una instancia estática pública se expone a través de la interfaz que se inicializa solo una vez (debido a que el campo es final). Además, la instancia casi siempre se recupera utilizando Spring o una fábrica genérica que desacopla la interfaz de la implementación.
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static final Vehicle INSTANCE = getInstance();
private static Vehicle getInstance() {
return new Car(); // or use Spring/factory here
}
}
}
// Which allows to retrieve a singleton instance using...
Vehicle someVehicle = Vehicle.Default.INSTANCE;
En pocas palabras: parece que este es un patrón singleton / factory personalizado, que básicamente permite exponer una instancia o un singleton a través de su interfaz. Con respecto a las desventajas, se han mencionado algunas en las respuestas y comentarios a continuación. Hasta ahora, la ventaja parece radicar en su conveniencia.
Vehicle.Default
debería moverse hacia arriba en el espacio de nombres del paquete como una clase de fábrica, por ejemplo VehicleFactory
.
Vehicle.Default.getInstance() != Vehicle.Default.getInstance()