The Singleton Pattern in Java

Es gibt einige Möglichkeiten wie das Singleton Pattern in Java umzusetzen ist. Hier möchte ich einen kurzen Überblick über diese geben und einige Stärken bzw. Schwächen aufdecken.

a synchronized method

Eine der verbreitetsten Methoden das Singleton Pattern  zu implementieren, listet unter anderem auch Wikipedia als Java Referenz dafür. Durch einen privaten Konstruktor wird der Zugriff von außen vermieden, die einzige Instanz in einer private static Variable abgelegt. Über eine synchronisierte Methode erhält man Zugriff auf diese Variable. Ist die Instanz noch nicht erzeugt worden wird dies nachgeholt, anstonsten die bereits abgelegte retourniert. Der Nachteil dieser Variante ist durch seinen Thread sicheren Zugriff gegegeben. Damit, dass die Instanz nur durch eine synchronisierte Methode aufrufbar ist, blockieren sich mehrere Threads die darauf zugreifen wollen gegenseitig.

public class Singleton {

	/* Privates Klassenattribut, welches beim ersten Laden erzeugt wird. */
	private static Singleton instance;

	/* Privater Konstruktor um Zugriff von außen zu verhindern */
	private Singleton() {}

	/* Statische Methode liefert die einzige Instanz der Klasse zurück */
	public synchronized static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

a public final field

Um die Problematik der synchronisierten Zugriffe zu umgehen, muss das Objekt früher erzeugt werden und nicht erst bei Zugriff auf eine Methode der Klasse. Dazu wird z.B. ein public static final Field genutzt, auf das zugegriffen werden kann. Dieses wird bei Initialisierung der Klasse befüllt und kann dannach nicht mehr verändert werden. Wermutstropfen: über Reflektion kann man dennoch auf den privaten Konstruktor zurückgreifen.

public class Singleton {

	/* Instanzierung von Singleton */
	public static final Singleton INSTANCE = new Singleton();

	/* Privater Konstruktor um Zugriff von außen zu verhindern */
	private Singleton() {}
}

a private final field accessable by a public method

Eine Vermischung beider Varianten ist folgendes Beispiel

public class Singleton {

	/* Instanzierung von Singleton */
	private static final Singleton INSTANCE = new Singleton();

	/* Privater Konstruktor um Zugriff von außen zu verhindern */
	private Singleton() {}

	/* Methode zum Zugriff auf die Instanz */
	public static Singleton getInstance(){
		return INSTANCE;
	}
}

Vermeidet die Mängel der ersten Methode, offeriert aber den selben Schwachpunkt wie die zweite hier genannten Methode. Gemeinsam mit der zeiten Methode, dem public final Field, sind diese beiden Ansätze der Ersten jedoch vorzuziehen, da bei ihnen durch das Feld eindeutig hervorgeht, dass es sich um ein Singleton handelt. Das final Field wird immer das selbe Objekt referenzieren. Ist noch zusätzlich eine Methode vorhanden um auf das final Field zuzugreifen erhält man einen weiterne Vorteil. Man kann das Konzept des Singletons wieder aufgeben ohne die API ändern zu müssen. Der Client kann damit weiter über die getInstance Methode eine Instanz erhalten.

a singleton by enum

Seit Java 1.5 ist eine weitere Möglichkeit entstanden. Ein Enum mit nur einem einzigen Element:

public enum Singleton{
	INSTANCE;
}

Dieser Ansatz ist serialisierbar, kurz gehalten, sicher vor Mehrfachinstanzierung und vereint die Vorteile der vorher angesprochenen Ansätze. Dieser Weg ist der empfohlene Weg und sollte zukünftig gegangen werden.

Weitere Literatur

[1] Singleton Pattern auf Wikipedia

[2] Design Patterns Head First

[3] Entwurfsmuster GoF

Ähnliche Artikel:

Was ist ein Key-preserved table?

Schonmal mit einer Oracle Datenbank gearbeitet? Und auch schon diesen ORA bekommen?

ORA-01752: cannot delete from view without exactly one key-preserved table

Nun, was hat es damit auf sich?

Eine Tabelle ist dann „key-preserved“ wenn jeder Schlüssel der Tabelle auch der Schlüssel des Joins sein kann. Das bedeutet dass der eindeutige Schlüssel durch einen Join erhalten bleibt. Dies liegt nicht dem Inhalt des Tables zugrunde sondern dem Schema, welchem die Tabelle zugrundeliegt.

Am besten ist das wohl an einem Beispiel erklärt:

create view fehlermeldungen as
select f.id fid, f.name fname, m.id mid, m.name mname
from modul m, fehler f
where f.modul_id = m.id;

Wenn wir die Daten der View aufrufen bekommen wir beispielhaft folgende Werte:

FID        FNAME      MID        MNAME
---------- ---------- ---------- ----------
       101 NULLP              10 MAIN
       102 ARRAY              10 MAIN
       103 STRING             10 MAIN
       104 DATE               20 GUI
       105 STRING             20 GUI
       106 NULLP              20 GUI
       107 NULLP              20 GUI
       108 STRING             20 GUI
8 rows selected.

Der Key der zugrundeliegenden Tabelle fehler blieb erhalten. Anhand dieses Keys kann auch in der View in der der Join erfolgte immernoch ein einzelner Datensatz extrahiert bzw. identifiziert werden. Der Key der Tabelle modul hingegen ist zwar für die Tabelle eindeutig, ist aber kein Key des Joins mehr. In dem Fall ist also f.id key-preserved und m.id nicht.
Die Ursache liegt bereits bei der Verbindung der beiden Tabellen. Die Modul.id wird als Fremdschlüssel auf der Tabelle Fehler geführt und muss dort somit nicht unique sein.

Oracle selbst erlaubt eine Tabelle je View die ihren Schlüssel in der View behält, wenn man auf dieser Datenmanipulationen zulassen möchte. Sind zwei oder mehr schlüssel-erhaltende Tabellen in der View enthalten, gelten für die einzelnen Datenmanipulationsvorgänge spezielle Regeln die befolgt werden müssen. Dazu später mehr.

Um dieses Problem zu umgehen bleiben einem somit nur 3 Möglichkeiten:

  1. Die Datenstruktur soweit anpassen oder eine neue View bauen die die Vorraussetzungen erfüllt.
  2. Anstatt mit der View direkt mit den Tabellen zu arbeiten.
  3. Das Problem umschiffen indem man mit „Instead of“-Trigger an die View gehängt arbeitet.

Was man beachten muss wenn man eine View erstellt und diese für weitere Operationen heranziehen will:

  • UPDATE: Alle Spalten, in denen Information upgedated werden soll, müssen von einem key-preserved Table stammen. Wenn in der View die CHECK OPTION gesetzt ist müssen alle JOIN Spalten und Spalten von Tabellen die mehr als einmal referenziert sind, von dem Update geschützt sein.
  • DELETE: Es darf nur einen key-preserved Table in der View geben, dieser Table kann zwar mehrfach in der View vorkommen, jedoch nur wenn die View die CHECK OPTION gesetzt hat.
  • INSERT: Alle Spalten, in die Information neu eingetragen werden, müssen vom key-preserved Table kommen. Hierbei darf die View nicht die CHECK OPTION gesetzt haben.

Kurz zur WITH CHECK OPTION Klausel:
Ist die View mit dieser Klausel ausgestattet werden schon vor dem Einfügen oder Verändern von Datensetzen die WHERE Klauseln überprüft. Würde ein neuer Datensatz nicht durch die Einschränkungen der WHERE Klausel als gültig erkannt werden, wird die Aktion bereits vor der Ausführung verhindert bzw. nicht durchgeführt.

Quellen:
[1] http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96521/views.htm#4054

[2] http://ora-01752.ora-code.com/

[3] http://www.praetoriate.com/t_grid_rac_admin_db_links.htm

Ähnliche Artikel:

Geschwindigkeit des Seitenaufbaus messen unter php

Um zu messen wie lange der Seitenaufbau einer Webseite dauert genügt schon ein recht simples PHP-Script. Dabei werden zu Beginn und am Ende des Seitenaufbaus jeweils eine Zeitmessung durchgeführt. Die Differenz daraus liefert uns die Zeit des Seitenaufbaus, welche wir am Schluss noch ausgeben.

Feel free to use this script on your pages ;)

// in the beginning/header of the page
;



// at the end/footer of the page

Ähnliche Artikel:

quakelive with some problems on linux (libpng newer than 1.2)

Unfortunately there are some problems displaying the graphic of quakelive when using libpng newer than 1.2. Within the last weeks my archlinux offerd me to update it to 1.4. Afterwards quakelive was broken. It displayed only some artefakts where icons or text was before.

Quake Live broken visualization
Screenshot was taken from: http://www.quakelive.com/forum/showthread.php?&t=43859

To fix this problem there is a simple workaround:

  1. Check if libpng12.so exist ( ls -lha /usr/lib/libpng12.so )
  2. Install libpng 1.2 (on arch e.g. yaourt -S libpng12 )
  3. Start firefox using this command: LD_PRELOAD=“/usr/lib/libpng12.so“ /usr/bin/firefox

For more comfort a i wrote myself an alias by editing .bashrc and adding this line:

alias quakelive="LD_PRELOAD=/usr/lib/libpng12.so /urs/bin/firefox"

by the next login the alias will be available and if you wish you can add an shortcut to your startmanu or panel etc.

usagehint: if an instance of firefox is already running you have to stop it first

Ähnliche Artikel:

Google Street View Autos in Wien gesichtet

Am Parkplatz vor dem Palais Schwarzenbergplatz [1] wurden heute gegen 13:30 die Google Street View Autos gesichtet. Sie sind wohl schon oder bald in Wien Unterwegs. Wer jetzt schon Wien betrachten will kann dies auf der rumänischen Seite: http://www.norc.at

Dass die Wagen bald hier wieder unterwegs sein könnten wurde schon auf computerwelt in folgendem Artikel bekanntgegeben: http://www.computerwelt.at/detailArticle.asp?a=127085

Google Street View Autos
Google Street View Autos

So standen sie am Parkplatz rum, wobei der rechte Wagen etwas ramponiert war. Man beachte den Spiegel auf der Fahrerseite. – ein paar Schrammen seitlich zeigten dass man beim Fotographieren wohl die Breite seines Wagens aus den augen verlieren kann ;)

Google Street View Autologo
Google Street View Autologo

Nicht ganz typisch ist das Google Logo auf dem Wagen. Aber bitte auch auf der Suchmaschinenseite ist das Logo regelmäßig anders verpackt!

Google Street View Wagenaufsatz
Google Street View Wagenaufsatz

Leider waren die Kameras eingepackt. Die Vorrichtung lässt ein Kippen der Kameras zu um durch Brücken oder ähnliches durchzupassen.

[1] http://de.wikipedia.org/wiki/Palais_Schwarzenberg_am_Schwarzenbergplatz

Ähnliche Artikel: