In den letzten Monaten bin ich ein paar Mal über die folgende Technik / das folgende Muster gestolpert. Ich kann jedoch scheinbar keinen bestimmten Namen finden und bin mir auch nicht hundertprozentig sicher, welche Vor- und Nachteile er hat.
Das Muster lautet wie folgt:
Innerhalb einer Java-Schnittstelle wird wie gewohnt eine Reihe gängiger Methoden definiert. Bei Verwendung einer inneren Klasse geht jedoch eine Standardinstanz über die Schnittstelle verloren.
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
}
}
}
Für mich liegt der größte Vorteil darin, dass ein Entwickler nur über die Oberfläche und nicht über deren Implementierungen Bescheid wissen muss, z. B. für den Fall, dass er schnell eine Instanz erstellen möchte.
Vehicle someVehicle = Vehicle.Default.getInstance();
someVehicle.accelerate();
Außerdem habe ich gesehen, dass diese Technik zusammen mit Spring verwendet wird, um Instanzen abhängig von der Konfiguration dynamisch bereitzustellen. In dieser Hinsicht kann dies auch bei der Modularisierung hilfreich sein.
Trotzdem kann ich das Gefühl nicht loswerden, dass dies ein Missbrauch der Schnittstelle ist, da sie die Schnittstelle mit einer ihrer Implementierungen koppelt. (Prinzip der Abhängigkeitsinversion usw.) Kann mir jemand erklären, wie diese Technik heißt und welche Vor- und Nachteile sie hat?
Aktualisieren:
Nach einiger Zeit zum Nachdenken überprüfte ich erneut und stellte fest, dass die folgende Singleton-Version des Musters weitaus häufiger verwendet wurde. In dieser Version wird eine öffentliche statische Instanz über die Schnittstelle verfügbar gemacht, die nur einmal initialisiert wird (da das Feld endgültig ist). Außerdem wird die Instanz fast immer mit Spring oder einer generischen Factory abgerufen, die die Schnittstelle von der Implementierung entkoppelt.
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;
Kurz gesagt: Es scheint, dass dies ein benutzerdefiniertes Singleton- / Factory-Muster ist, mit dem im Grunde genommen eine Instanz oder ein Singleton über ihre Schnittstelle verfügbar gemacht werden kann. In Bezug auf die Nachteile wurden einige in den nachstehenden Antworten und Kommentaren genannt. Bisher scheint der Vorteil in seiner Bequemlichkeit zu liegen.
Vehicle.Default
als Factory-Klasse in den Package-Namespace hochgeschoben werden, z VehicleFactory
.
Vehicle.Default.getInstance() != Vehicle.Default.getInstance()