{"id":2470,"date":"2013-10-14T19:39:23","date_gmt":"2013-10-14T17:39:23","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=2470"},"modified":"2013-10-14T19:39:23","modified_gmt":"2013-10-14T17:39:23","slug":"singleton-in-java","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2013\/10\/singleton-in-java\/","title":{"rendered":"Singleton in Java"},"content":{"rendered":"<p>Ein Singleton ist eine Klasse, von der es in einer Anwendung nur ein Exemplar gibt. N\u00fctzlich ist das f\u00fcr Dinge, die es nur genau einmal in einer Applikation geben soll, und davon gib es einige Beispiele:<\/p>\n<p>\u00b7 Eine grafische Anwendung hat nur ein Fenster.<\/p>\n<p>\u00b7 Eine Konsolenanwendung hat nur je einen Eingabe-\/Ausgabestrom.<\/p>\n<p>\u00b7 Alle Druckauftr\u00e4ge wandern in eine Drucker-Warteschlage.<\/p>\n<p>Unbestreitbar ist, dass es einmalige Objekte gibt, variantenreich ist jedoch der Weg dahin. Im Prinzip l\u00e4sst sich unterscheiden zwischen einem Ansatz, bei dem<\/p>\n<p>a) ein Framework sich um den einmaligen Aufbau des Objekts k\u00fcmmert und dann auf Anfrage das Objekt liefert oder<\/p>\n<p>b) wir selbst in Java-Code ein Singleton realisieren.<\/p>\n<p>Die bessere L\u00f6sung ist ein Framework zu nutzen, namentlich CDI, Guice, Spring, Java EE, doch Java SE enth\u00e4lt keines davon, weswegen wir zur Demonstration den expliziten Weg gehen.<\/p>\n<p>Die technischen Realisierungen sind vielseitig; in Java bieten sich zur Realisierung von Singletons Aufz\u00e4hlungen (enum) und normale Klassen an. In Folgendem wollen wir ein Szenario annehmen, bei dem eine Anwendung zentral auf Konfigurationsdaten zur\u00fcckgreifen m\u00f6chte.<\/p>\n<h3>Singletons \u00fcber Aufz\u00e4hlungen<\/h3>\n<p>Eine guter Weg f\u00fcr Singletons bieten Aufz\u00e4hlungen \u2013 auf den ersten Blick scheint ein enum nicht daf\u00fcr gemacht, denn eine Aufz\u00e4hlung impliziert ja irgendwie mehr als ein Element \u2013 doch die Eigenschaften vom enum sind perfekt f\u00fcr ein Singleton. Die Idee dabei ist, genau ein Element anzubieten, gerne INSTANCE genannt, was letztendlich ein Exemplar der Aufz\u00e4hlungskasse wird, und die normalen Methoden:<\/p>\n<p>public <b>enum Configuration<\/b> {<\/p>\n<p><b>INSTANCE<\/b>;<\/p>\n<p>private Properties props = new Properties( System.getProperties() );<\/p>\n<p>public String getVersion() {<\/p>\n<p>return &quot;1.2&quot;;<\/p>\n<p>}<\/p>\n<p>public String getUserDir() {<\/p>\n<p>return props.getProperty( &quot;user.dir&quot; );<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>Der Typ Configuration deklariert neben der sp\u00e4ter \u00f6ffentlichen statischen Variable INSTANCE auch noch eine interne Variable props, die von der Aufz\u00e4hlung genutzt werden kann, um dort Zust\u00e4nde abzulegen oder zu erfragen. Wir machen das im Beispiel nur lesend \u00fcber getUserDir().<\/p>\n<p>Ein Nutzer greift wie \u00fcblich auf die enum-Eigenschaften zu:<\/p>\n<p>System.out.println( <b>Configuration.INSTANCE.getVersion()<\/b> ); \/\/ 1.2<\/p>\n<p>System.out.println( <b>Configuration.INSTANCE.getUserDir()<\/b> ); \/\/ C:\\Users\\&#8230; <\/p>\n<h3>Singletons \u00fcber Klassen<\/h3>\n<p>Ein alternativer Weg \u2013 und der \u00fcbliche vor Java 5 \u2013 arbeit mit einer Klasse und privatem Konstruktor, zusammen mit einer statischen Anfrage-Methode, die das Objekt liefert:<\/p>\n<p>public class Configuration2 {<\/p>\n<p>private static final <b>Configuration2 INSTANCE = new Configuration2()<\/b>;<\/p>\n<p>public final <b>static Configuration2 getInstance() {<\/b><\/p>\n<p><b>return INSTANCE;<\/b><\/p>\n<p><b>}<\/b><\/p>\n<p>private Configuration2() {<\/p>\n<p>}<\/p>\n<p>private Properties props = new Properties( System.getProperties() );<\/p>\n<p>public String getVersion() {<\/p>\n<p>return &quot;1.2&quot;;<\/p>\n<p>}<\/p>\n<p>public String getUserDir() {<\/p>\n<p>return props.getProperty( &quot;user.dir&quot; );<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>Interessant sind einmal der private Konstruktor und zum anderen die statische Anfrage-Methode getInstance(). Wenn ein Konstruktor privat ist, bedeutet das noch lange nicht, dass keine Exemplare mehr erzeugt werden k\u00f6nnen. Ein privater Konstruktor besagt nur, dass er von au\u00dfen nicht sichtbar ist \u2013 aber die Klasse selbst kann ihn ebenso wie private Methoden \u00bbsehen\u00ab und zur Objekterzeugung nutzen. Objektmethoden kommen daf\u00fcr nicht in Frage, da \u00e4hnlich wie beim Henne-Ei-Problem ja vorher ein Objekt n\u00f6tig w\u00e4re. Es bleiben somit die statischen Methoden als Erzeuger. Und das ist das, was wir wollen: Keine Exemplare von au\u00dfen, nur von innen. Und da die statische Variable INSTANCE ja genau ein Objekt referenziert, kann die statische Methode diese Referenz nach au\u00dfen geben.<\/p>\n<p>Die Nutzung der zweiten Variante ist nicht sonderlich unterschiedlich, hat aber wohl eine andere Syntax, sodass ein Refactoring von einer L\u00f6sung in die andere Code\u00e4nderungen nach sich zieht:<\/p>\n<p>System.out.println( <b>Configuration2.getInstance().getVersion()<\/b> ); \/\/ 1.2<\/p>\n<p>System.out.println( <b>Configuration2.getInstance().getUserDir()<\/b> ); \/\/ C:\\Users\\&#8230;<\/p>\n<p>Oftmals findet sich in Implementierungen eines Singletons noch eine Optimierung, in dem erst in getInstance() das Exemplar aufgebaut wird. Dazu muss aber noch die Methode mit synchronized ausgezeichnet werden, was vor nebenl\u00e4ufigen Zugriffen sch\u00fctzt, sodass nur ein Thread die Methode betreten kann und ein potenziell anderer Thread so lange warten muss, bis der erste Thread die Methode wieder verlassen hat.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ein Singleton ist eine Klasse, von der es in einer Anwendung nur ein Exemplar gibt. N\u00fctzlich ist das f\u00fcr Dinge, die es nur genau einmal in einer Applikation geben soll, und davon gib es einige Beispiele: \u00b7 Eine grafische Anwendung hat nur ein Fenster. \u00b7 Eine Konsolenanwendung hat nur je einen Eingabe-\/Ausgabestrom. \u00b7 Alle Druckauftr\u00e4ge [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11],"tags":[],"class_list":["post-2470","post","type-post","status-publish","format-standard","hentry","category-insel"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=2470"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2470\/revisions"}],"predecessor-version":[{"id":2471,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2470\/revisions\/2471"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=2470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=2470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=2470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}