Best Practice Singleton und Singleton mit Instanz zu anderer Klasse -Pattern

EinNickname9

Bekanntes Mitglied
Hi, zuerst mal der Code:

Singleton ohne Instanz zu anderer Klasse:
Java:
public class TheClazz1 {
    public static final ASingleton singleton = new ASingleton();

    public void testMethod() {
        new AnotherClazz().testMethod();
    }

    public static void main(String[] args) {
        TheClazz1 clazz1 = new TheClazz1();
        clazz1.testMethod();
    }
}

class ASingleton {
    public void importantMethod(double importantParameter) {
        System.out.println("importantParameter = " + importantParameter);
        // to do: implementation
    }
}

class AnotherClazz {
    public void testMethod() {
        TheClazz1.singleton.importantMethod(42);
    }
}

Singleton mit Instanz zu anderer Klasse:
Java:
public class TheClazz2 {
    public static ASingleton2 singleton;

    public TheClazz2() {
        // other things in constructor here...

        singleton = new ASingleton2(this);
    }

    public void testMethod() {
        new AnotherClazz2().testMethod();
    }

    public void testMethod2(double importantParameter) {
        System.out.println("importantParameter = " + importantParameter);
    }

    public static void main(String[] args) {
        TheClazz2 clazz2 = new TheClazz2();
        clazz2.testMethod();
    }
}

class ASingleton2 {
    private final TheClazz2 clazz2;

    public ASingleton2(TheClazz2 importantReference) {
        this.clazz2 = importantReference;
    }

    public void importantMethod(double importantParameter) {
        clazz2.testMethod2(importantParameter);
        // to do: implementation
    }
}

class AnotherClazz2 {
    public void testMethod() {
        TheClazz2.singleton.importantMethod(42);
    }
}

Dazu ein paar Fragen:
- Wäre der Code so gut?
- Braucht man zwingend das "static"?
- Entspricht Zweites noch dem Prinzip der losen Kopplung?
- Gibt es bei Zweites auch die Möglichkeit, die Klassenvariable "final" zu machen? Wenn ja, wie?

Vielen Dank für eure Geduld :)
 

Jw456

Top Contributor
Hallo beide Beispiele haben nichts mit einem Sigeltone zu tun. Sind keine.

Bei einem Sigeltone wird die Instanz de
eigenen Klasse in einer static Variablen in der Klasse gehalten.
Eine andere Klasse Instanz kann sich die Instanz über eine Methode erfragen.
Davon sehe ich nichts in deinen Code.
 
K

kneitzel

Gast
Dann wäre erst einmal wichtig zu klären, was denn ein Singleton ist.

Da verweise ich einfach einmal auf Wikipedia:

Der ganz wichtige Punkt ist dabei:
nur ein Objekt zu einer Klasse existieren darf

Es darf nur eine einzige Instanz der Singleton Klasse geben!

Damit fällt jedes Erstellen in einer anderen Klasse aus, den wenn eine andere Klasse eine Instanz erstellen kann, dann könnte das ja prinzipiell weitere Klassen ebenso.

Die Lösung umfasst also einfach nur:
- der Konstruktor ist private. Dadurch kann keine andere Klasse eine Instanz erzeugen. (Auf regulärem Weg - von irgendwelchen Tricks gehen wir mal nicht aus!)
- Du hast eine statische private Variable, die eine Instanz halten kann.
- Du hast eine statische Methode, mit der Du auf die private Variable zugreifen kannst. Dort findet sich dann (Thread sicher!) eine Prüfung, ob die Variable gesetzt wurde ehe diese dann zurück gegeben wird.

Das sieht dann z.B. so aus:
Java:
  public final class Singleton {
 
      /**
       * Privates Klassenattribut,
       * wird beim erstmaligen Gebrauch (nicht beim Laden) der Klasse erzeugt
       */
      private static Singleton instance;
 
      /** Konstruktor ist privat, darf nicht von außen instanziiert werden. */
      private Singleton() {}
 
      /**
       * Statische Methode "getInstance()" liefert die einzige Instanz der Klasse zurück.
       * Ist synchronisiert und somit thread-sicher.
       */
      public synchronized static Singleton getInstance() {
          if (instance == null) {
              instance = new Singleton();
          }
          return instance;
      }
  }

Wenn man es vereinfachen möchte, dann könnte man auf die Idee kommen, das etwas zu vereinfachen:
Das geht etwas in die Richtung, die Du gemacht hast.

Aber dazu einfach dann noch der Link:

Da kommt dann auch das, was ich immer mache: Ich nutze kein synchronized bei der Methode. Statt dessen baue ich einen doppelten Check. Nur wen bei getInstance die instanz noch null ist gehe ich einen geschützten Block. In diesem prüfe ich erneut und erzeuge ggf. die Instanz.
Das Locking kostet halt auch Performance und das muss man ja nicht ständig haben.
 
K

kneitzel

Gast
Und natürlich auch von mir der Hinweis: Das was Du gemacht hast ist in keiner Weise ein Singleton. Du hast lediglich eine Konstante erstellt, die dann benutzt wird. Etwas in der art mag auch ausreichend sein. Singletons sind etwas, das ich eigentlich immer versuche zu vermeiden.

Die Frage ist immer: Darf es wirklich immer nur eine Instanz geben? Nur weil eine Applikation immer nur eine Instanz nutzen möchte, muss es kein Singleton sein. Singletons sind blöd zu testen und verkomplizieren vieles. Und das oft ganz ohne Zwang.

Eine Applikation kann sich (z.B. von einem ApplicationContext) immer eine Instanz von etwas geben lassen. Dann wäre die betreffende Klasse immer noch kein Singleton. Das ist aber ok, da ich mich darauf festgelegt habe: Zugriff erfolgt immer über den ApplicationContext.

Kleine Ausführung zu dem ApplicationContext - das wird aber jetzt vernutlich für Dich viel zu weit gehen, aber ich will es schon einmal erwähnt haben:
ApplicationContext ist nicht willkürlich gewählt - so heißt die Klasse z.B. bei Spring um an sogenannte Beans zu kommen. Sie wird aber nicht oft direkt genutzt, denn wenn man sowas einmal vom Prinzip her hat, dann hat man einen Baustein für sogenannte Dependency Injection. Du holst dir Dinge nicht mehr explizit sondern Du lässt Dir Alles direkt geben und Du schreibst sogenannte Annotations wie @Autowired an Dinge dran. Damit sind wir aber dann jetzt sehr weit weg vom eigentlichen Singleton Pattern. Singleton taucht da dann als Begriff zwar auch wieder auf aber das ist dann da kein Pattern sondern lediglich ein sogenannter Bean Scope.
 

temi

Top Contributor
Bloch erwähnt noch eine Möglichkeit ein gutes Singleton zu implementieren:
Java:
public enum Singleton {
    INSTANCE;
    
    public void doSomething() {
        // ...
    }
}
 

EinNickname9

Bekanntes Mitglied
Also, die Beiträge von @kneitzel verstehe ich nicht so richtig. (Dennoch vielen Dank für Deine Antworten!) Meine Frage war ja, was ich mache, wenn das Singleton eine Instanz/Referenz zu einer anderen Klassen (hier: zur GUI) braucht? Also eine Aggregation vorliegt. Dann muss ich doch das reine Singleton -Pattern verletzen. Damit verletze ich auch das Prinzip der losen Kopplung, oder?

Und, in der Tat, im etwas weiteren Sinne meiner Frage geht es hier um Dependency Injection.
 

EinNickname9

Bekanntes Mitglied
Ich habe jetzt gerade diesen Abschnitt gelesen: https://de.wikipedia.org/wiki/Lose_Kopplung#Software-Architektur
Globale Variablen, öffentliche Attribute, Singletons oder beispielsweise die Speicherung von Softwarezuständen in einer Datenbank vergrößern automatisch die Schnittstelle von Komponenten und sind daher zu vermeiden.

Lose Kopplung führt dazu, dass Änderungen in einer Komponente nur dann Änderungen in einer anderen Komponente bedingen, wenn die Änderungen die Schnittstelle betreffen. Lose Kopplung hat daher einen direkten Einfluss auf die Wartbarkeit einer Software.
Aber was könnte ich stattdessen einsetzen? :confused:

Konkret geht es um eine MyLogging-Klasse, die immer erreichbar sein muss, und die Infos in DB, File, Konsole und GUI loggt.
 

Jw456

Top Contributor
Singleton ist schon eine Möglichkeit um immer von überall an daten die in der Singleton Kasse gespeichert sind zu kommen. Wenn die Klasse in der die Daten in die Sigelten gespeichert wurden zerstört wird. Um nun von eine anderen neuen Kasse auf genau die gleichen Daten zu kommen. Ist singleton schon nicht schlecht.

Aber was du machst ist keine Singleton.

Keinzel hat dir genügend Links gegeben wie eine Singleton Klasse ausschaut.


Lose Kopplung .... soetwas gibt es bei Singleton nicht .
 

temi

Top Contributor
Singleton ist schon eine Möglichkeit um immer von überall an daten die in der Singleton Kasse gespeichert sind zu kommen.
Allerdings ist das eine mißbräuchliche Verwendung des Singleton-Patterns, die auch zu seinem schlechten Ruf geführt hat. Die Intention des Singleton ist es einzig und allein, nur eine einzige Instanz einer Klasse zu erlauben. Du kannst diese Instanz auch ganz normal z. B. per Konstruktor an eine andere Klasse übergeben (das würde auch für die erwähnte Logging-Instanz gelten).
 

Jw456

Top Contributor
Die Instanz der Singleton Klasse host du dir mit einer Methode die in der Singleton Klasse ist und die dir genau diese Instanz zurück gibt. Und mit genau Instanz kannst du genauso weiterarbeiten als hättest du in der neue Instanz der Singleton Klasse erstellt.
 

temi

Top Contributor
Die Instanz der Singleton Klasse host du dir mit einer Methode die in der Singleton Klasse ist und die dir genau diese Instanz zurück gibt. Und mit genau Instanz kannst du genauso weiterarbeiten als hättest du in der neue Instanz der Singleton Klasse erstellt.
Das ist natürlich richtig. Da muss ich jetzt erst mal drüber nachdenken. ;)

Mir geht es allerdings eher darum, die Abhängigkeit von dieser Klasse klar zu machen und das geht üblicherweise über Konstruktor-Injektion.
 

Jw456

Top Contributor
Das ist natürlich richtig. Da muss ich jetzt erst mal drüber nachdenken. ;)

Mir geht es allerdings eher darum, die Abhängigkeit von dieser Klasse klar zu machen und das geht üblicherweise über Konstruktor-Injektion.
Singleton macht für mich sinn, wenn eine Klasse von einer Klasse in eine andere Klasse gegangen wird, und die aufrufende Klasse zerstört wird. Wie es zb das Android Framework macht, wenn es zu einer neuen Activty geht. Und man Daten aus der alten Klasse haben will.
 
Zuletzt bearbeitet:

Jw456

Top Contributor
Ich habe jetzt gerade diesen Abschnitt gelesen: https://de.wikipedia.org/wiki/Lose_Kopplung#Software-Architektur

Aber was könnte ich stattdessen einsetzen? :confused:

Konkret geht es um eine MyLogging-Klasse, die immer erreichbar sein muss, und die Infos in DB, File, Konsole und GUI loggt.


 

EinNickname9

Bekanntes Mitglied
Wenn es kein Singleton ist, was ist es dann?

Ich beschreibe nochmal kurz die Anforderungen:
Es soll eine Klasse MyLogging geben. Diese Klasse soll Strings (einzelne Zeilen, mit Datum/Uhrzeit versehen) in DB, File, Konsole und GUI loggen. Die Klasse soll während der gesamten Laufzeit der Anwendung von "überall" erreichbar sein (oder zumindest ab dem Zeitpunkt, an dem die GUI initialisiert wurde). Es soll immer nur eine Instanz dieser Klasse geben. Die Klasse hat eine Abhängigkeit zur GUI, d. h., sie braucht zwingend eine Referenz von der GUI, um funktionieren zu können.

Wie würdet ihr diese Anforderung am besten umsetzen?
 
K

kneitzel

Gast
Wenn es kein Singleton ist, was ist es dann?

Ich beschreibe nochmal kurz die Anforderungen:
Es soll eine Klasse MyLogging geben. Diese Klasse soll Strings (einzelne Zeilen, mit Datum/Uhrzeit versehen) in DB, File, Konsole und GUI loggen. Die Klasse soll während der gesamten Laufzeit der Anwendung von "überall" erreichbar sein (oder zumindest ab dem Zeitpunkt, an dem die GUI initialisiert wurde). Es soll immer nur eine Instanz dieser Klasse geben. Die Klasse hat eine Abhängigkeit zur GUI, d. h., sie braucht zwingend eine Referenz von der GUI, um funktionieren zu können.

Wie würdet ihr diese Anforderung am besten umsetzen?
Also diese Anforderung kann mit einem Singleton umgesetzt werden. Aber was Du gebracht hast ist einfach eine Konstante zu deklarieren. Das geht natürlich auch. Aber es hat nichts mit Singleton zu tun.

Wenn Du es mit einem Singleton lösen willst, dann kannst Du dieses Singleton Pattern umsetzen. Dazu hast Du diverse Ideen und Möglichkeiten genannt bekommen. Aber wie Du schon festgestellt hast: man braucht da nicht zwangsläufig eine Singleton Klasse.
 

Jw456

Top Contributor
Wenn du in eine echten singleton Klasse. Eine Methode einen setter machst, dem du die Instanz der Gui übergibst und der Setter es dann in einer Instanz Variablen in der Singelton hält hast du was du suchst.

Oder du gibst der Speicher Methode in der Singelton Klasse auch die Instanz der Gui als Parameter mit. Also die Instanz und die Werte die gespeichert werden sollen.
 

Jw456

Top Contributor
als Singleton in etwa so
Java:
public final class MyLogging {
    private static MyLogging instance;

    /**
     * Konstruktor ist privat, darf nicht von außen instanziiert werden.
     */
    private MyLogging() {
    }

    public synchronized static MyLogging getInstance() {
        if (instance == null) {
            instance = new MyLogging();
        }
        return instance;
    }

    public void logDaten(Gui giu, String daten) {
        // logen der daten mit der Gui Instanz

    }
}





public class Gui extends JFrame {

   ...

    public Gui() {
        ...
        }


    public static void main(String[] args) {

        Gui meinApplikation = new Gui();
        MyLogging.getInstance().logDaten(meinApplikation,"hallo");


    }
}
 

mrBrown

Super-Moderator
Mitarbeiter
Es soll eine Klasse MyLogging geben. Diese Klasse soll Strings (einzelne Zeilen, mit Datum/Uhrzeit versehen) in DB, File, Konsole und GUI loggen. Die Klasse soll während der gesamten Laufzeit der Anwendung von "überall" erreichbar sein (oder zumindest ab dem Zeitpunkt, an dem die GUI initialisiert wurde). Es soll immer nur eine Instanz dieser Klasse geben. Die Klasse hat eine Abhängigkeit zur GUI, d. h., sie braucht zwingend eine Referenz von der GUI, um funktionieren zu können.
Dreh die Abhängigkeit zur GUI um, indem du ein Interface dazwischen schiebst und was in Richtung Listener-Pattern nutzt.

Ganz grob:

Java:
class MyLogger {

  public interface Log {
    void logLine(String line);
  }

  public void addLog(Log log);
}

Java:
class LogGui implements Log {...}

Java:
LogGui logGui = ...

MyLogger.getInstance().addLog(fileLog);
...
MyLogger.getInstance().addLog(logGui);
 

mrBrown

Super-Moderator
Mitarbeiter
Und kurz zum Singleton: Man sollte Unterscheiden zwischen Umsetzung des SIngleton Patterns und generell Singletons, die zB durch Container bereitgestellt werden.
Das Pattern ist für die meisten Zwecke ungeeignet, zB durch die harte Kopplung und statischen Zustand (hat @temi ja beides schon genannt) – Singletons an sich sind aber absolut kein Problem und oftmals super nutzbar, grad auch in Verbindung mit Dependency Injection.
 

EinNickname9

Bekanntes Mitglied
Wenn du in eine echten singleton Klasse. Eine Methode einen setter machst, dem du die Instanz der Gui übergibst und der Setter es dann in einer Instanz Variablen in der Singelton hält hast du was du suchst.
Danke 🥰
Das trifft beides den Nagel auf den Kopf 🥰 und das kannte ich noch nicht...

Ich werde das so machen: Statische Variable, die die Instanz hält, Lazy singleton und Setter.
 
K

kneitzel

Gast
Ah, ok, dann gilt das natürlich schon für den Code von @kneitzel :)
Ich habe keinen eigenen Code geliefert und nur Links mit Beschreibung geliefert. Die ganzen Links kann man übrigens durchlesen und dann findet man recht viele, nützliche Hinweise (Allerdings nicht die Variante mit der inneren Klasse, ebenso wie die enum Variante. Die wurden beide nicht erwähnt.).
 

Jw456

Top Contributor
Das sieht dann z.B. so aus:
Java:
  public final class Singleton {
 
      /**
       * Privates Klassenattribut,
       * wird beim erstmaligen Gebrauch (nicht beim Laden) der Klasse erzeugt
       */
      private static Singleton instance;
 
      /** Konstruktor ist privat, darf nicht von außen instanziiert werden. */
      private Singleton() {}
 
      /**
       * Statische Methode "getInstance()" liefert die einzige Instanz der Klasse zurück.
       * Ist synchronisiert und somit thread-sicher.
       */
      public synchronized static Singleton getInstance() {
          if (instance == null) {
              instance = new Singleton();
          }
          return instance;
      }
  }
Und was ist das?
Post #3

Ok Der Code war aus dem Wiki link.

Gut die Methode die ich hinzugefügt habe ist nicht Thread sicher es ging aber um das Prinzip was dem TE etwas deutlicher werden sollte.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Singleton Instanz löschen Allgemeine Java-Themen 5
Neoline Klassen Singleton Klasse buchmanager Allgemeine Java-Themen 19
J Singleton Allgemeine Java-Themen 5
Z deserialize singleton Allgemeine Java-Themen 9
A Singleton threadsafe Allgemeine Java-Themen 8
A Datei als Object einlesen und das Object als Singleton instance setzen. Allgemeine Java-Themen 13
T ActionListener und Singleton Allgemeine Java-Themen 15
S Singleton Entwurfsmuster Allgemeine Java-Themen 20
T So eine Art Singleton-Factory? Allgemeine Java-Themen 3
S Singleton-Klasse und ThreadLocal-Klasse von abstrakter Klasse ableiten? Allgemeine Java-Themen 2
S Singleton hier sinnvol? Allgemeine Java-Themen 20
T Zugriff auf Singleton verkürzen - Namespaces?? Allgemeine Java-Themen 20
B Volatile Frage: Reicht es nur den Singleton als volatile zu deklarieren? Allgemeine Java-Themen 4
Iron Monkey Singleton mit Parameter Allgemeine Java-Themen 14
G Singleton Frage: Allgemeine Java-Themen 17
M Singleton und Vererbung? Allgemeine Java-Themen 45
R Wo initilisiere ich eine Liste in einem Singleton? Allgemeine Java-Themen 2
M Java Garbage Collector Frage (Singleton Pattern) Allgemeine Java-Themen 13
B Generisches Singleton implementieren Allgemeine Java-Themen 12
H Singleton und MultiThreading [erledigt] Allgemeine Java-Themen 3
S Singleton Pattern mit Generics Allgemeine Java-Themen 4
P SingleTon Allgemeine Java-Themen 5
M zwei Threads - ein singleton-Objekt Allgemeine Java-Themen 3
RaoulDuke Agent als Singleton Thread Allgemeine Java-Themen 7
S singleton vs. static Allgemeine Java-Themen 7
P Singleton vs static Allgemeine Java-Themen 19
K Singleton vererben Allgemeine Java-Themen 15
E Singleton vererben Allgemeine Java-Themen 10
E Frage zu Singleton Allgemeine Java-Themen 22
D Design Pattern: Singleton Allgemeine Java-Themen 4
K Sequenzdiagramm für Singleton-Muster Allgemeine Java-Themen 5
J Verständnis Frage zur Instanz, Objekte, Instanzierung, Referenz Allgemeine Java-Themen 14
Thallius HTTPS Request mit unbekannter Instanz Allgemeine Java-Themen 24
S Speicherverwaltung bei Instanz- und Klassenvariablen JS vs. Java Allgemeine Java-Themen 2
T MEthodenauruf testen, wenn instanz erst erzeugt wird Allgemeine Java-Themen 0
OnDemand InetAddress Instanz Allgemeine Java-Themen 4
T Klassen Instanz einer Klasse ausserhalb des Jar Allgemeine Java-Themen 2
J Ist eine Instanz von einem bestimmten Object Typ? Allgemeine Java-Themen 6
B JavaFX fxml, die selbe Instanz der Klasse Allgemeine Java-Themen 4
E Auf Java-Objekt aus anderer Instanz zugreifen Allgemeine Java-Themen 26
DStrohma In abstrakter Klasse Konstruktor von Instanz implementieren Allgemeine Java-Themen 11
S OOP Objekte als Return-Werte: Einen Klon zurückgeben oder Instanz auf das Feld? Allgemeine Java-Themen 10
V Serialisierung von Instanz eigener Klasse Allgemeine Java-Themen 5
Kr0e Reflection - Instanz einer Klasse erstellen, ohne Default-Constructor Allgemeine Java-Themen 15
sambalmueslie Benachrichtigung bei neuer Objekt-Instanz Allgemeine Java-Themen 5
L Object Instanz anhand eines Strings Allgemeine Java-Themen 10
M Object-Instanz in Date übersetzen Allgemeine Java-Themen 6
M Neue Instanz/Kopie einer unbekannten Klasse Allgemeine Java-Themen 7
M Instanz "von außen" erstellen unterbinden Allgemeine Java-Themen 3
S Neue Instanz eines Objekts erzeugen - Konstruktor erhaelt Parameter. Allgemeine Java-Themen 5
V Reflection - Field-Instanz und Annotations Allgemeine Java-Themen 6
S Instanz in einer Klasse erstellen, und dem Konstruktor die eigene Klasse mitgeben Allgemeine Java-Themen 4
J Instanz-Felder einer Klasse initialisieren Allgemeine Java-Themen 6
N Variablen eines Objektes (instanz) in einen Array lesen Allgemeine Java-Themen 7
M Instanz von Datenbankklasse Allgemeine Java-Themen 5
M Instanz erstellen Allgemeine Java-Themen 3
flashfactor Prüfen ob bereits eine Instanz gestartet ist Allgemeine Java-Themen 2
A Nur eine Instanz eines Programms ausführen Allgemeine Java-Themen 3
T Instanz einer Interface abgeleiteten Klasse erzeugen Allgemeine Java-Themen 3
I size einer instanz Allgemeine Java-Themen 9
minzel Instanz auslesen? Allgemeine Java-Themen 22
G überpüfen ob bereits instanz von java applikation läuft Allgemeine Java-Themen 4
B Instanz? Allgemeine Java-Themen 6
H Vererbung auch ohne erzeugung einer Instanz möglich? Allgemeine Java-Themen 3
B nur eine Instanz eines Programms laufen lassen Allgemeine Java-Themen 8
G Nur eine Instanz einer Applikation Allgemeine Java-Themen 4
G Instanz IDs Allgemeine Java-Themen 13
P Nur eine Instanz eines Programms zulassen, wie geht das? Allgemeine Java-Themen 15
J Instanz einer inneren Klasse Allgemeine Java-Themen 9
H Methode einer zur Laufzeit generierten Instanz aufrufen Allgemeine Java-Themen 2

Ähnliche Java Themen


Oben