{"id":964,"date":"2016-03-22T17:15:27","date_gmt":"2016-03-22T15:15:27","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=964"},"modified":"2016-03-07T11:16:06","modified_gmt":"2016-03-07T09:16:06","slug":"einzigartiges-einzelstueck-der-vereinzelung","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/einzigartiges-einzelstueck-der-vereinzelung\/","title":{"rendered":"Einzigartiges Einzelst\u00fcck der Vereinzelung"},"content":{"rendered":"<p>Hallo Spa\u00df-Coder.<\/p>\n<p>In unserem letzten Artikel zur Serie \u00fcber Entwurfsmuster haben wir uns mit der Erstellung von Produktfamilien besch\u00e4ftigt. In diesem Artikel werden wir uns nun um genau ein einziges Exemplar k\u00fcmmern. Es ist handelt sich um das sog. <strong>Einzelst\u00fcck <\/strong><i><strong>(<span lang=\"en\" xml:lang=\"en\">singleton<\/span>)<\/strong>.<\/i><\/p>\n<p>Wie die <a href=\"http:\/\/invidit.de\/blog\/maschinelle-erzeugnisse\/\" target=\"_blank\">Abstract Factory <\/a>dient auch das Singleton dazu, ein Objekt zu erstellen, mit dem wir dann weiterarbeiten k\u00f6nnen. Aber warum wollen wir das? Hier gelten die gleichen Gr\u00fcnde, die wir auch schon bei der Abstrakten Fabrik angef\u00fchrt haben. Wir wollen m\u00f6glichst auf <span style=\"color: #800080;\">new<\/span> verzichten, wenn wir uns in Teilen des Codes bewegen, die sich mit hoher Wahrscheinlichkeit \u00e4ndern werden.<\/p>\n<p>Beim Singleton geht es darum, genau ein Objekt f\u00fcr unsere gesamte Anwendung zu erstellen. Egal an welcher Stelle wir uns das Singleton holen, es ist immer <strong>genau dasselbe<\/strong>. Wenn wir also an einer Stelle der Anwendung einen Status des Sinlgeton-Objekts setzen, hat es an anderer Stelle noch genau denselben Status.<\/p>\n<p>Wann aber ist dieses Entwurfsmuster sinnvoll anzuwenden?<\/p>\n<p>&nbsp;<\/p>\n<h1>Das gleiche ist noch lange nicht dasselbe<\/h1>\n<p>Das Singleton findet Verwendung, wenn wir in unser Anwendung zentral auf das gleiche Objekt zugreifen m\u00f6chten. Beispiele daf\u00fcr sind etwa zentrale Konfigurationen oder etwa eine Protokollausgabe, bei der wir von allen Stellen der Anwendung in dasselbe Protokoll schreiben wollen.<\/p>\n<p>Vereinfacht gesagt, immer dann, wenn nur ein Objekt zu einer Klasse existieren darf und ein einfacher Zugriff auf dieses Objekt ben\u00f6tigt wird, ist die Verwendung des Singleton-Musters sinnvoll.<\/p>\n<h2>Beispiel<\/h2>\n<p>Schauen wir uns als Beispiel einmal an, wie wir einen zentralen Logger\u00a0 implementieren w\u00fcrden. Dazu erstellen wir eine Klasse Logger:<\/p>\n<pre class=\"lang:java decode:true\">public class Logger {\r\n\r\n    private static Logger instance;\r\n\r\n    private Logger() {\r\n    }\r\n\r\n    public static Logger getLogger() {\r\n        if (instance == null) {\r\n            instance = new Logger();\r\n        }\r\n        return instance;\r\n    }\r\n\r\n    public void Log(Object textToLog) {\r\n        System.out.println(textToLog);\r\n    }\r\n}<\/pre>\n<p>Der wichtigste Aspekt dieser Klasse ist, dass sie einen <strong>privaten Konstruktor<\/strong> enth\u00e4lt. Damit stellen wir sicher, das niemand eine Instanz dieser Klasse erstellen kann. Naja, wenigstens fast niemand. Eine Instanz brauchen wir schlie\u00dflich. Und wer hat Zugriff auf private Klassenmethoden? Genau, nur die Klasse selbst (und ihre inneren Klassen, aber darauf kommen wir bei einem anderen Muster nochmal zur\u00fcck). Das gilt in gleicher Weise f\u00fcr den Konstruktor.<\/p>\n<p>Nachdem wir nun also sichergestellt haben, dass nur wir eine Instanz unseres Loggers erstellen k\u00f6nnen, m\u00fcssen wir diesem aber auch zur\u00fcckgeben. Dazu enth\u00e4lt die Klasse eine <strong>statische<\/strong> <strong>Methode<\/strong> <em>getLogger()<\/em>. Diese Methode dient dazu, die eine Instanz unseres Loggers abzurufen. Wird die Methode das erste Mal aufgerufen, so wird die Instanz erstellt. Von da an wird immer genau diese eine Instanz zur\u00fcckgegeben.<\/p>\n<p>Dadurch ist immer dann, wenn wir irgendwo in unserem Code eine Protokollausgabe machen m\u00f6chten sichergestellt, dass wir dieselbe Instanz der Klasse <em>Logger<\/em> verwenden und somit immer an die gleiche Stelle protokollieren. Gut, oder?<\/p>\n<p>&nbsp;<\/p>\n<h1>Probleme des Singletons<\/h1>\n<p>Leider funktioniert unser obiger Code nicht gut. In kleinen, \u00fcberschaubaren Anwendungen, die nur in einem Thread arbeiten, ist unser Logger hinreichend gut. Versuchen wir aber nun mit zwei Threads gleichzeitig die Methode <em>getLogger()<\/em> aufzurufen, bekommen wir ein Problem.<\/p>\n<p>Schaut euch den o.g. Code noch einmal an und geht im Kopf mal durch, was passiert, wenn zwei Threads gleichzeitig die Methode aufrufen. Erkennt ihr das Problem?<\/p>\n<p>Wenn zwei Threads gleichzeitig in die Methode eintreten, ist die Variable <em>instance<\/em> f\u00fcr beide Threads null, es wird also jeweils eine Neue Instanz erstellt und zur\u00fcckgegeben. Diese sind dann nat\u00fcrlich unterschiedlich. Wie k\u00f6nnen wir das Problem l\u00f6sen?<\/p>\n<p>In Java hilft uns hier das Schl\u00fcsselwort <em>synchronized<\/em> an der Methode:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Synchronisierte Methode in Java\">public synchronized static Logger getLogger() {\r\n\tif (instance == null) {\r\n\t\tinstance = new Logger();\r\n\t}\r\n\treturn instance;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>In C# unterst\u00fctzt uns das Schl\u00fcsselwort lock, es ist aber ein wenig komplizierter zu verwenden. Hier ben\u00f6tigen wir noch ein Objekt, auf welchem wie die Sperre ausf\u00fchren k\u00f6nnen:<\/p>\n<pre class=\"theme:vs2012 lang:c# decode:true\" title=\"Synchronisierte Methode in C#\">private static Object locked = new Object();\r\n\r\npublic static Logger getLogger() {\r\n\tlock(locked) {\r\n\t\tif (instance == null) {\r\n\t\t\tinstance = new Logger();\r\n\t\t}\r\n\t\treturn instance;\r\n\t}\r\n}<\/pre>\n<p>Dadurch ist sichergestellt, dass auch wirklich nur eine Instanz erstellt wird, auch wenn aus unterschiedlichen Prozessen (Threads) heraus die Abfrage erfolgt.<\/p>\n<p>&nbsp;<\/p>\n<h2>Alles wird gut!<\/h2>\n<p>Damit ist alles gut, oder? Leider nicht. Wir haben zwar eine L\u00f6sung f\u00fcr das sog. Nebenl\u00e4ufigkeitsproblem gefunden, das kaufen wir aber teuer ein. Die Synchronisation von Code zwischen verschiedenen Prozessen ist teuer in der Laufzeit. Verwenden wir unser Singleton in unserer Anwendung h\u00e4ufig &#8211; und bei unserem Logger-Beispiel ist das nicht soo abwegig &#8211; hat das einen erheblichen schlechten Einfluss auf die Laufzeit unserer Anwendung.<\/p>\n<p>Wie aber wollen wir das Problem dann l\u00f6sen? Nun, zun\u00e4chst ist die Synchronisation tats\u00e4chlich der einzige Weg, das Problem der Nebenl\u00e4ufigkeit in den Griff zu bekommen. Wir k\u00f6nnen aber versuchen, das Problem mit der Performance in den Griff zu bekommen.<\/p>\n<p><strong>1.) Nichts tun<\/strong><\/p>\n<p>H\u00e4? Wie jetzt? Seit wann l\u00f6sen wir Probleme durch aussitzen? Naja, ganz so ist es nicht. Wenn wir unsere Methode <em>getLogger()<\/em> nur selten und nur in Performance-unkritischen Situationen verwenden, lassen wir den Code genau so wie er ist. Alles weitere ist unn\u00f6tige M\u00fche, die wir uns hier machen.<\/p>\n<p><strong>2.) Instanz immer initialisieren<\/strong><\/p>\n<p>Wir k\u00f6nnen daf\u00fcr sorgen, dass unsere Instanz niemals <em>null<\/em> ist. Dazu m\u00fcssen wir sie einfach beim Erstellen der Klasse instanziieren:<\/p>\n<pre class=\"lang:java decode:true\">public class Logger {\r\n\r\n    private static Logger instance = new Logger();\r\n [...]\r\n}<\/pre>\n<p>Da die Variable statisch ist, wird sie unmittelbar nach dem Laden der Klasse initialisiert. Ist also in unserem Beispiel immer mit einem Logger gef\u00fcllt. Das l\u00f6st das oben beschriebene Problem.<\/p>\n<p>Es k\u00f6nnte aber wieder zu einem neuen Problem f\u00fchren. N\u00e4mlich genau dann, wenn die Erstellung der Instanz sehr teuer ist, wir diese aber nicht immer in unserer Anwendung ben\u00f6tigen. Denken wir z.B. an eine Schnittstelle zu einem anderen System. Wird einer der Benutzer diese Schnittstelle anfragen? Lohnt es sich, die teure Initialisierung der Schnittstelle durchzuf\u00fchren, wenn wir das nicht wissen?<\/p>\n<p>Die Antwort ist nat\u00fcrlich &#8222;Nein&#8220;. Wir sollten in unserem Code nichts machen, was wir nicht auch brauchen.<\/p>\n<p><strong>3.) Teilsynchronisation<\/strong><\/p>\n<p>Kommt f\u00fcr uns weder die erste, noch die zweite L\u00f6sung infrage, m\u00fcssen wir uns ein wenig M\u00fche geben, die Synchronisation so performant wie m\u00f6glich zu halten. Dazu synchronisieren wir nicht die ganze Methode, sondern lediglich die Erstellung unserer Instanz.<\/p>\n<p>Das Ganze sieht in Java dann wie folgt aus:<\/p>\n<pre class=\"lang:java decode:true \" title=\"Teilsynchronisation in Java\">public class Logger {\r\n\r\n    private volatile static Logger instance;\r\n\r\n    private Logger() {\r\n    }\r\n\r\n    public static Logger getLogger() {\r\n        if (instance == null) {\r\n            synchronized(Logger.class) {\r\n                if (instance == null) {\r\n                    instance = new Logger();\r\n                }\r\n            }\r\n        }\r\n        return instance;\r\n    }\r\n\r\n    public void Log(Object textToLog) {\r\n        System.out.println(textToLog);\r\n    }\r\n}<\/pre>\n<p>Wir pr\u00fcfen also zun\u00e4chst ohne Synchronisation, ob unsere Instanz schon gef\u00fcllt ist. Falls nicht, und nur in diesem Fall und nur <strong>genau einmal<\/strong>, f\u00fchren wir die Erstellung der Instanz synchronisiert durch. Damit die Abfrage auf die Variable aber auch thread\u00fcbergreifend funktioniert, ist es erforderlich, dass unsere Variable <em>instance<\/em> mit dem Schl\u00fcsselwort <em>volatile<\/em> versehen wird. Das sorgt daf\u00fcr, dass die Variable vor jedem Zugriff auf Aktualit\u00e4t gepr\u00fcft und ggf. aktualisiert wird. Dieser Vorgang ist wesentlich g\u00fcnstiger, als <em>synchronize<\/em>.<\/p>\n<p>&nbsp;<\/p>\n<p>In C# haben wir es nun ein wenig einfacher, da wir die Variable ja bereits definiert haben und wir ohnehin Bl\u00f6cke und nicht Methoden mit dem Schl\u00fcsselwort <em>lock<\/em> verwenden:<\/p>\n<pre class=\"theme:vs2012 lang:c# decode:true \" title=\"Teilsynchronisation in C#\">public class Logger {\r\n\r\n    private static Logger instance;\r\n\tprivate static Object locked = new Object();\r\n\r\n    private Logger() {\r\n    }\r\n\r\n    public static Logger getLogger() {\r\n        if (instance == null) {\r\n            lock(locked) {\r\n\t\t\t\tif (instance == null) {\r\n\t\t\t\t\tinstance = new Logger();\r\n\t\t\t\t}\r\n\t\t\t}\r\n        }\r\n        return instance;\r\n    }\r\n\r\n    public void Log(Object textToLog) {\r\n        System.out.println(textToLog);\r\n    }\r\n}<\/pre>\n<p>Die Funktionsweise ist hier identisch, nur brauchen wir kein weiteres Schl\u00fcsselwort f\u00fcr die Variable, da wir hier mit einem separaten Objekt arbeiten. Die Sprachkonzepte zwischen Java und C# sind ein wenig unterschiedlich, die Idee dahinter bleibt aber dieselbe.<\/p>\n<p>&nbsp;<\/p>\n<p>Wichtig ist es bei der Suche nach der besten L\u00f6sung, sich zu vergegenw\u00e4rtigen, wie oft ich das Singleton ben\u00f6tige und wie aufwendig die Erstellung ist. Die L\u00f6sung ist dementsprechend der obigen M\u00f6glichkeiten zu w\u00e4hlen.<\/p>\n<p>&nbsp;<\/p>\n<h1>Warum muss immer ich das machen??<\/h1>\n<p>Wenn ein Framework eingesetzt wird, welches die Verwaltung von Singletons unterst\u00fctzt &#8211; z.B. das SpringFramework &#8211; sollte auf die eigene Implementierung verzichtet werden. Insbesondere bei komplexen Anwendungen mit Multithreading ist es &#8211; wie oben beschrieben &#8211; wichtig, dass das Singleton sauber implementiert ist. Wenn uns ein Framework diese Arbeit abnimmt, sollten wir dies auch nutzen.<\/p>\n<p>&nbsp;<\/p>\n<h1>Zusammenfassung<\/h1>\n<p>Das Singleton ist ein wichtiges uns sehr hilfreiches Muster. Es hat seine T\u00fccken, aber wenn man diese kennt, sind sich auch kein gr\u00f6\u00dferer Schrecken mehr als Knecht Ruprecht, nachdem man erfahren hat, dass er in Wirklichkeit gar nicht existiert.<\/p>\n<p>Wir hoffen, dass die Beispiele euch gen\u00fcgend Anhaltspunkte daf\u00fcr gegeben haben, wann und insbesondere wie das Muster sinnvoll eingesetzt werden kann.<\/p>\n<p>Viel Spa\u00df beim Ausprobieren<\/p>\n<p>Eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p>Den Code zu unserem Beispiel k\u00f6nnt ihr auf Github finden:<\/p>\n<ul>\n<li>https:\/\/github.com\/invidit\/CodeQuality\/tree\/master\/DesignPattern\/Singleton<\/li>\n<\/ul>\n<p>Dieser Artikel basiert neben unseren Erfahrungen auf den Ausf\u00fchrungen aus:<\/p>\n<ul>\n<li><a href=\"https:\/\/de.wikipedia.org\/wiki\/\" target=\"_blank\">https:\/\/de.wikipedia.org\/wiki\/<\/a>\n<ul>\n<li><a title=\"Singleton (Entwurfsmuster)\" href=\"https:\/\/de.wikipedia.org\/wiki\/Singleton_%28Entwurfsmuster%29\" target=\"_blank\">Einzelst\u00fcck<\/a> <i title=\"Prototyp (Entwurfsmuster)\">(<span lang=\"en\" xml:lang=\"en\">singleton<\/span>)<\/i><\/li>\n<\/ul>\n<\/li>\n<li>Freeman, Eric &amp; Freeman, Elisabeth &#8211; Entwurfsmuster von Kopf bis Fu\u00df &#8211; O&#8217;Reilly, 2006.<\/li>\n<li><a href=\"http:\/\/www.zdnet.de\/39198058\/java-datenzugriffe-mit-dem-schluesselwort-i-volatile-i-synchronisieren\/\" target=\"_blank\">http:\/\/www.zdnet.de\/39198058\/java-datenzugriffe-mit-dem-schluesselwort-i-volatile-i-synchronisieren\/<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df-Coder. In unserem letzten Artikel zur Serie \u00fcber Entwurfsmuster haben wir uns mit der Erstellung von Produktfamilien besch\u00e4ftigt. In diesem Artikel werden wir uns nun um genau ein einziges Exemplar k\u00fcmmern. Es ist handelt sich um das sog. Einzelst\u00fcck (singleton). Wie die Abstract Factory dient auch das Singleton dazu, ein Objekt zu erstellen, mit [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":969,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[90],"tags":[130,135],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/964"}],"collection":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=964"}],"version-history":[{"count":8,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/964\/revisions"}],"predecessor-version":[{"id":1014,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/964\/revisions\/1014"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/969"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}