Das kommt auf deinen UseCase und Requirments darauf an.
Wenn du mit Spring und Dependency Injection arbeitest kannst du auf statische Zugriffe fast ausschliesslich verzichten und POJOs verwenden.
Wenn du aber eine zentrale Klasse benoetigst um allgemeine Methoden zu definieren kann auch static der richtige Weg sein. Als Beispiel schau dir mal java.lang.Math an.
... Aber static zieht halt die bekannten Probleme nach sich... keine Vererbung!
public class A {
static Double parseString(String s) {
return Double.parseDouble(s);
}
}
public class B extends A {
}
public class Main {
public static void main(String[] args) {
Double dbl = B.parseString("3.59");
System.out.println("dbl = " + dbl);
}
}
public class A {
static Double parseString(String s) {
return Double.parseDouble(s);
}
}
public class B extends A {
static Double parseString(String s) {
return Math.round(super.parseString(s));
}
}
Da ist [c]parseString[/c] zwar sichtbar, wird aber nicht vererbt. Z.B. geht folgendes nicht, was bei einer nicht-statischen Methode funktionieren würde:
Java://... public class B extends A { static Double parseString(String s) { return Math.round(super.parseString(s)); } }
public class B extends A {
static Double parseString(String s) {
return Math.round(A.parseString(s));
}
}
Double a = A.parseString(..);
Double b = B.parseString(..);
Meine Klasse ist eine Formatterklasse, die Strings "zurechtschneidet".
Wenn ich nur ein Objekt von einer Klasse brauche, mache ich alles statisch.
Methoden sollte man, vereinfacht gesagt, statisch machen, wenn sie keinen internen Zustand eines Objektes verändern (sondern nur "Utility-Methoden" sind, die eine Eingabe bekommen und eine Ausgabe ausspucken)
Das Kriterium "ICH brauche nur eine Instanz" ist aber unbdeutend. (Das Singleton verwendet man, wenn es immer nur eine Instanz geben DARF). Jemand anderes braucht vielleicht drei oder 143 Instanzen davon.
Auf der einen Seite schreibe ich schon fast reflexartig alles so modular und unabhängig wie möglich, auf der anderen Seite fühlt es sich für mich komisch an, wenn "gewöhnliche" Klassenmethoden statisch sind.
Das ist für mich irgendwie ein Widerspruch. Ich bilde Klassen, um die Funktionalität logisch zu kapseln und dann verwende ich darin wieder ein Konzept, dass eher gegen die einzelnen Kapseln gerichtet ist?
Meist verschiebe ich das dann in Hilfsklassen, mit nur statischen Methoden.
class SortableList extends ArrayList
{
public void sort()
{
Collection.sort(this);
}
}
interface List<T> ...
{
public extension void sort()
default Collections.sort;
}
2) Du hast eine Klasse, deren Methoden oder Variablen von überall aus oder von sehr vielen verschiedenen Stellen aus erreichbar sein sollen -> public static
Dafür hat man dann das Singleton an der Backe, SoC wird verletzt weil Erzeugung und Zugriff gleichzeitig geregelt werden, dann der static Zugriff... jedes DI Framework bietet bessere Alternativen um ein Objekt nur einmal zu erzeugen, sogar schon "pseudo-standartisiert" mit javax.inject.SingletonMit dem Singleton lässt man dann alle überzähligen Aufrufe ins Leere laufen und hat Ruhe.
Nun, wenn du ein GoF Singleton geschrieben hast, dann hast du eine statische Methode (zB. getInstance) mit der man auf das Singleton zugreifen kann, dann wohl einen privaten Konstruktor, wie ein Objekt erzeugt wird, ist unweigerlich damit verbunden, wie man es erhält, und dann hat deine Klasse wohl noch irgendeine FunktionialitätInwiefern liegt das denn alles zusammen in einer Klasse?
@Singleton
public class Anything {
...
}
So wie "globale Variable" vielleicht?und bestimmte "globale" Instanzen der Anwendung anzusprechen.
Offensichtlich machst du da nicht viel mit, denn ein GoF Singleton ist definitiv ein "Showstopper" wenn es ums testen geht (ohne EasyMock zB.).Beim Testen meinst Du wegen Überschreiben? Das Problem hatte ich z.B. bei Junit noch nicht. Aber ich mach in der Richtung auch nicht viel.
Viele Leute "missbrauchen" das Singleton-Pattern eben nur als globale Variable, weil das so schön praktisch ist, dass man von überall drauf zugreifen kann. Der eigentlich Zweck, nämlich zu verhindern, dass es mehr als ein Objekt gibt, ist da völlig nebensächlich. Ich kann mir durchaus Fälle vorstellen, wo man mehr als einen Thread- oder Connection-Pool hat. Oder viele Konfigurationen. Und wenn man dann von Singleton auf was vernünftiges Umstellen will, sitzt man erstmal tagelang da, um seinen Code zu refaktorieren und die globalen Referenzen weg zu bekommen. Da sind die angesprochenen DI-Frameworks schon sehr viel praktischer. Von derTestbarkeit ganz zu schweigen.Ich weiß nicht, was Du mit "globaler Variable" meinst. Ich hab dort zum Beispiel Werte aus Konfigurationsdateien hinterlegt.
Oder Laufzeitinformationen wie zum Beispiel den aktuellen Modus der Applikation. Dazu Instanzen die von "überall" genutzt werden können und z.B. begrenzte Ressourcen kapseln (Pools für Threads/Speicher, ...)
Klar, wenn man nicht isoliert tested, dann gibt es auch keine Probleme beim testen wenn Singletons involviert sindDa kam sowas als Problem nie wirklich auf.
Ich nehme an, dass du noch nicht mit DI gearbeitet hast, das "holen" an sich wird überflüssig, weil die Objekte schon alles bekommen was sie brauchen, ohne statische Methoden von anderen Klassen aufzurufen, weniger Kopplung/direkte abhängigkeiten (loose coupling).Wenn ich nur eine "Registry" brauche, dann bau ich doch auch nur das. Die hol ich mir dann "am höchsten Punkt", von mir aus auch über eine statische Methode.
Tja, wieso kommen Leute auf die Idee ein GoF Singleton zu nutzen?Aber wieso sollte jemand auf die Idee kommen den Singletonkram mit privatem Konstruktor etc. noch dazubasteln, wenn sich dadurch gar nichts ändert?
public abstract class Base {
public Base Base.create(int type) {
switch( type ) {
case 1: return new Foo1();
case 2: return new Foo2();
default: throw IllegalArgumentException();
}
}
}
public class Foo1 extends Base {
}
Wieso muss die Datei jedesmal geladen werden?
Und wenn Du eben mit Konfigurationen in Dateien arbeitest, wie willst Du das dann umgehen, wenn Du das Pattern wechselst?
Ich seh da keinen Zusammenhang zum Singleton. Ob ich eine Konfigurationsdatei verwende ist doch nicht von "static" abhängig.
Etwas ganz anderes tun und sich dann zu freuen, dass man andere Probleme hat, bringts ja nun auch nicht.
public class MitGoFSingleton {
public String formatiereDatenGemaessBenutzereinstellungen() {
UserProperties props = UserProperties.getSingletonInstance();
...[aufwendige Berechnungen]...
return result;
}
}
public class MitDependencyInjection {
@Autowired
private UserPropertiesProvider propsProvider;
public String formatiereDatenGemaessBenutzereinstellungen() {
UserProperties props = propsProvider.getProperties();
...[aufwendige Berechnungen]...
return result;
}
}
Eben, "Leute" die Singletons schreiben sind zB. kein gutes Vorbild.@ maki, naja es gibt immer irgendwelche Leute, die seltsame Dinge machen. Sich an denen zu orientieren find ich jetzt nicht so passend für so ein Thema.
tfa, ich verstehe nach wie vor nicht, was das Auslesen der Datei (oder von mir aus auch DB) mit dem Pattern zu tun hat.
Irgendwann muss mal ein "setValue()" gemacht werden. Ob Du nun Singletons, DI, oder was auch immer verwendest, wenn die Konfiguration in Flatfiles liegt, musst Du sie auch dort holen.
Würdest Du wirklich sagen, dass eure Schwierigkeiten an dem Wörtchen "static" irgendwo im Code hängen?
public String methodToTest(...) {
String result = BusinessHomeFactory.getInstance().getComplexBusinessLogic().doIt();
// do something
return result;
}
public class BusinessHomeFactory {
//static getInstance()
public ComplexBusinessLogic getComplexBusinessLogic() {
if( inTestMode() ) { return new MockedComplexBusinessLogic(); } else { // do JNDI lookup }
}
}
Aber das zwingt euch doch euer Singleton nicht auf. Spring benutzt doch selbst auch welche.
Du kannst euer Singleton ja auf eine synchronisierte Map umstellen und schauen, ob sich dann was verbessert.
Richtig, könnte man auch ohne DI besser machen. Habe ich aber leider keine Kontrolle drüber, unser Projekt ist international (federführend sind unsere amerikanischen Freunde, die sich grundsätzlich nichts sagen lassen) und leidet an permanenter Featuritis: "Werk XY braucht unbedingt das und das, lass uns bloß mit Infrastruktur in Ruhe"Natürlich ist es unschön, wenn ihr solche Probleme habt. Aber diese Dinge besser zu machen, ist doch nicht erst mit Spring und DI plötzlich möglich geworden.
Ja. Siehe Schalentiers Antwort.Würdest Du wirklich sagen, dass eure Schwierigkeiten an dem Wörtchen "static" irgendwo im Code hängen?
Das wollen wir doch. Siehe mein Beispiel oben. Nur haben diese Spring-Singletons nichts mit dem statisch verdrahteten, GoF-Pattern "Singleton" zu tun. Das ist was völlig anderes.Landei, ich meine, dass Du eure Singletons doch auch so verwalten kannst, wie z.B. Spring das mit seinen Singletons macht.
(DefaultSingletonBeanRegistry ...)