Frage

Seien wir ehrlich. Das Singleton-Muster ist höchst umstritten Thema mit Horden Programmierern auf beide Seiten des Zauns. Es gibt diejenigen, die wie die Singleton fühlen nichts mehr ist dann eine glorifizierte globale Variable, und andere, die durch Muster schwören und es unaufhörlich verwenden. Ich will nicht die Singleton Kontroverse im Herzen liegen meine Frage, aber. Jeder kann ein Tug-of-Krieg haben und kämpfen um und sehen, wer für alle gewinnt meinetwegen . Was ich versuche zu sagen, ich glaube nicht, dass es nur eine richtige Antwort ist, und ich versuche, nicht absichtlich parteiisch Gezänk entflammen. Ich bin einfach interessiert in Singleton-Alternativen , wenn ich die Frage stellen:

Gibt es irgendwelche spezifischen Alternativen zu den GOF Singleton-Muster?

Zum Beispiel, viele Male, wenn ich das Singleton-Muster in der Vergangenheit verwendet haben, bin ich einfach interessiert an der Erhaltung der Zustand / Werte einer oder mehrerer Variablen. Der Staat / Wert der Variablen kann jedoch zwischen jeder Instanziierung der Klasse erhalten wird unter Verwendung von statischen Variablen anstelle die Singleton-Muster.

Was andere Idee haben Sie?

EDIT: „, wie richtig die Singleton verwenden“ Ich weiß nicht wirklich dies ein weiterer Beitrag über sein will Noch einmal, ich bin auf der Suche nach Möglichkeiten, es zu vermeiden. Für Spaß, ok? Ich glaube, ich bin in der besten Film-Trailer Stimme eine rein akademische Frage zu stellen: „In einem Paralleluniversum, wo es kein Singleton ist, was können wir tun?“

War es hilfreich?

Lösung

Alex Miller in " Patterns I Hate " zitiert die folgenden:

"Wenn ein Singleton wie die Antwort scheint, finde ich, ist es oft klüger:

  1. Erstellen Sie eine Schnittstelle und eine Standard-Implementierung Ihrer Singleton
  2. Erstellen Sie eine einzelne Instanz der Standardimplementierung an der „Spitze“ des Systems. Diese in einem Frühling-Config sein könnten, oder in Code oder in einer Vielzahl von Arten definierten abhängig von Ihrem System.
  3. Übergeben Sie die einzige Instanz in jede Komponente, die es (Dependency Injection)
  4. braucht

Andere Tipps

, um die richtige Art und Weise zu verstehen, Singletons zu umgehen, müssen Sie verstehen, was mit Singletons falsch ist (und globaler Staat im Allgemeinen):

Singletons verstecken Abhängigkeiten.

Warum ist das wichtig?

Da Wenn Sie verbergen die Abhängigkeiten, die Sie neigen dazu, den Überblick über die Stärke der Kopplung zu verlieren.

Sie könnten argumentieren, dass

void purchaseLaptop(String creditCardNumber, int price){
  CreditCardProcessor.getInstance().debit(creditCardNumber, amount);
  Cart.getInstance().addLaptop();
}

ist einfacher als

void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, 
                    String creditCardNumber, int price){
  creditCardProcessor.debit(creditCardNumber, amount);
  cart.addLaptop();
}

, aber zumindest die zweite API macht deutlich, genau das, was die Methode der Mitarbeiter sind.

So ist die Art und Weise Singletons zu Umgehung ist nicht statische Variablen oder Service-Locators zu verwenden, aber die Singleton-Klassen in Instanzen zu ändern, die in den Anwendungsbereich instanziiert werden, wo sie Sinn und injiziert in die Komponenten und Verfahren machen, die sie benötigen . Sie können einen IoC-Framework verwenden, um dies zu handhaben, oder Sie können es manuell tun, aber das Wichtigste ist, Ihren globalen Zustand loszuwerden und machen die Abhängigkeiten und Kooperationen explizit.

Die beste Lösung, die ich habe über gekommen ist die Fabrik Muster mit Instanzen von Klassen zu konstruieren. Unter Verwendung der Muster, können Sie versichert , dass es nur eine Instanz einer Klasse, die unter den Objekten gemeinsam genutzt wird, die es verwenden.

mir, obwohl es schwierig sein würde, zu verwalten, aber nachdem diese Blog-Post zu lesen "Wo die alle haben Singletons gegangen?" , es scheint so natürlich. Und als beiseite, es hilft viel mit Ihren Unit-Tests zu isolieren.

Zusammenfassend, was müssen Sie tun? Immer wenn ein Objekt von einem anderen abhängt, wird es eine Instanz davon erhält nur durch den Konstruktor (kein neues Schlüsselwort in Ihrer Klasse).

class NeedyClass {

    private ExSingletonClass exSingleton;

    public NeedyClass(ExSingletonClass exSingleton){
        this.exSingleton = exSingleton;
    }

    // Here goes some code that uses the exSingleton object
}

Und dann die Fabrik.

class FactoryOfNeedy {

    private ExSingletonClass exSingleton;

    public FactoryOfNeedy() {
        this.exSingleton = new ExSingletonClass();
    }

    public NeedyClass buildNeedy() {
        return new NeedyClass(this.exSingleton);
    }
}

Wie Sie Ihr Werk nur einmal instanziiert werden, wird es eine einzige Instantiierung exSingleton sein. Jedes Mal, wenn buildNeedy, die neue Instanz von NeedyClass nennen mit exSingleton gebündelt werden.

Ich hoffe, das hilft. Bitte weisen darauf hin, keine Fehler.

Frühling oder anderer IoC-Container hat eine recht gute Arbeit darin. Da die Klassen erstellt werden und außerhalb der App selbst verwaltet wird, kann der Behälter einfach Klassen Singletons machen und sie injizieren, wo nötig.

Sie sollen nicht aus dem Weg zu gehen, um jedes Muster zu vermeiden. Die Verwendung eines Muster ist entweder eine Design-Entscheidung oder eine natürliche Passform (es fällt nur an Ort und Stelle). Wenn Sie ein System entwerfen, haben Sie die Wahl, ein Muster verwenden entweder oder das Muster nicht verwenden. Sie sollten jedoch nicht aus dem Weg gehen zu alles zu vermeiden, was letztlich eine Designwahl ist.

Ich vermeide nicht die Singleton-Muster. Entweder es ist angemessen und ich verwende es oder es ist nicht angemessen, und ich verwende es nicht. Ich glaube, dass es so einfach wie das ist.

Die Angemessenheit (oder deren Fehlen) des Singleton, hängt von der Situation ab. Es ist eine Design-Entscheidung, die getroffen werden müssen, und die Folgen dieser Entscheidung muss verstanden werden (und dokumentiert).

Die Singleton Muster existieren, weil es Situationen geben, wenn ein einzelnes Objekt benötigt wird, eine Reihe von Dienstleistungen zur Verfügung zu stellen .

Auch wenn dies ist der Fall, dass ich immer noch den Ansatz der Schaffung Singletons betrachten, indem eine globales statisches Feld / Eigenschaft mit , die der Instanz, nicht angemessen. Es ist unangemessen, weil sie eine Abhängigkeit im Code zwischen dem statischen Feld erstellen und dem Objekt nicht, die Dienste das Objekt bereitstellt.

So anstelle des klassischen, Singletonmuster, empfehle ich mit Service-Container den Service ‚wie‘ Muster verwenden , wobei anstelle des Singleton durch ein statisches Feld verwendet wird, erhalten Sie einen Verweis auf sie aa Verfahren durch die Art des Dienstes anfordert erforderlich.

*pseudocode* currentContainer.GetServiceByObjectType(singletonType)
//Under the covers the object might be a singleton, but this is hidden to the consumer.

anstelle von einzelnen globalen

*pseudocode* singletonType.Instance

Auf diese Weise, wenn Sie Typ eines Objekts von Singleton, um etwas anderes ändern möchten, müssen Sie und einfach Zeit, es zu tun. Auch als ein und zusätzlichen Nutzen Sie müssen um nicht passieren zuzuteilen Objektinstanzen zu jeder Methode.

Siehe auch Inversion of Control , ist die Idee, dass von Singletons direkt an den Verbraucher ausgesetzt wird, können Sie eine Abhängigkeit zwischen dem Verbraucher schaffen und die Objektinstanz, nicht die Objektdienste durch das Objekt zur Verfügung gestellt.

Meine Meinung ist, auf verbirgt die Verwendung der Singleton-Muster, wann immer möglich, da es nicht immer möglich ist, es zu vermeiden, oder wünschenswert ist.

Monostate (in Robert C. Martin Agile Software Development beschrieben) ist eine Alternative zu Singleton. In diesem Muster sind die Daten der Klasse alle statisch, sondern die Getter / Setter sind nicht statisch.

Zum Beispiel:

public class MonoStateExample
{
    private static int x;

    public int getX()
    {
        return x;
    }

    public void setX(int xVal)
    {
        x = xVal;
    }
}

public class MonoDriver
{
    public static void main(String args[])
    {
        MonoStateExample m1 = new MonoStateExample();
        m1.setX(10);

        MonoStateExample m2 = new MonoStateExample();
        if(m1.getX() == m2.getX())
        {
            //singleton behavior
        }
    }
}

Monostate hat ein ähnliches Verhalten wie Singletons tut dies aber in einer Weise, wo der Programmierer nicht unbedingt der Tatsache bewusst ist, dass ein Singleton verwendet wird.

Wenn Sie einen Singleton verwenden ein einzelnes Datenobjekt zu repräsentieren, könnten Sie stattdessen ein Datenobjekt übergeben um als Methodenparameter.

(obwohl, würde ich argumentieren, dies der falsche Weg ist, einen Singleton in erster Linie zu verwenden)

Wenn Ihr Problem ist, dass Sie Zustand halten wollen, möchten Sie eine MumbleManager Klasse. Bevor Sie mit einem System anfangen zu arbeiten, schafft Ihr Client eine MumbleManager, wo Mumble der Name des Systems ist. Zustand wird durch die beibehalten. Die Chancen stehen Ihre MumbleManager eine Eigenschaft Tasche enthalten, die Ihren Zustand hält.

Diese Art von Stil fühlt sich sehr C-ähnliche und nicht sehr Objekt wie - Sie werden feststellen, dass Objekte, die Ihr System definieren werden alle einen Verweis auf die gleiche MumbleManager haben

.

Verwenden Sie ein einfaches Objekt und ein Factory-Objekt. Die Fabrik ist verantwortlich für die Überwachung der Instanz und die Ebene Objektdetails nur mit den Konfigurationsinformationen (es enthält zum Beispiel) und Verhalten.

Eigentlich, wenn Sie direkt von Grund auf neu entwerfen Singeltons auf die Vermeidung, können Sie nicht um zu arbeiten, haben nicht Singletons mit von statischen Variablen. Wenn statische Variablen verwenden, werden Sie auch ein Singleton mehr oder weniger zu schaffen, der einzige Unterschied ist, dass Sie unterschiedliche Objektinstanzen erstellen, aber intern alle sie sich verhalten, als ob sie ein Singleton verwendet haben.

Können Sie vielleicht ein detailliertes Beispiel geben, wo Sie einen Singleton verwenden oder wenn ein Singleton zur Zeit verwendet wird und Sie versucht, mit ihm zu vermeiden? Dies könnte Menschen helfen, eine Phantasie Lösung zu finden, wie die Situation überhaupt ohne Singleton behandelt werden könnte.

Übrigens, ich persönlich habe keine Probleme mit Singletons und ich kann die Probleme anderer Menschen haben in Bezug auf Singletons nicht verstehen. Ich sehe nichts Schlechtes über sie. Das heißt, wenn Sie sie nicht zu missbrauchen. Jede geeignete Technik kann missbraucht werden, und wenn missbraucht wird, wird es zu negativen Ergebnissen führen. Eine andere Technik, die häufig missbraucht wird, ist die Vererbung. Dennoch würde niemand sagen Erbe etwas schlecht ist, nur weil einige Leute missbrauchen es schrecklich.

für mich persönlich viel vernünftige Weise à etwas zu implementieren, wie Singleton verhält sie vollständig statische Klasse (statische Elemente, statische Methoden, statische Eigenschaften) verwenden. Die meiste Zeit ich es auf diese Weise implementieren (ich kann nicht glauben, von irgendwelchen Verhaltensunterschiede aus Sicht des Benutzers)

Ich denke, der beste Ort, um die Singletons der Polizei ist in der Klasse Design-Ebene. Zu diesem Zeitpunkt sollten Sie in der Lage sein, die Wechselwirkungen zwischen den Klassen zu kartieren und sehen, ob etwas absolut, auf jeden Fall, dass erfordern nur 1 Instanz dieser Klasse ist immer in Existenz jederzeit der Anwendungen Lebens.

Wenn das der Fall ist, dann haben Sie einen Singleton. Wenn Sie Singletons in als Bequemlichkeit werfen während der Codierung dann sollten Sie wirklich Ihr Design sein erneuten Besuch und auch stoppen die Codierung Singletons :)

Und ja, ‚Polizei‘ ist das Wort, das ich hier gemeint und nicht ‚zu vermeiden‘. Die Singleton ist nicht etwas zu vermeiden (in der gleichen Art und Weise, dass goto und globalen Variablen sind nicht etwas zu vermeiden). Stattdessen sollten Sie es verwenden werden, zu überprüfen und sicherzustellen, dass es die beste Methode ist, zu bekommen, was Sie effektiv gemacht werden sollen.

ich Singletons verwenden meist als „Methoden Container“, ohne Staat überhaupt. Wenn ich brauche diese Methoden mit vielen Klassen zu teilen und will die Last der Instanziierung zu vermeiden und die Initialisierung ich einen Kontext / Sitzung erstellen und alle Klassen dort zu initialisieren; alles, was auf der Sitzung verweist hat auch Zugriff auf die „Singletons“ dabei enthalten sind.

Nachdem in einem intensiv objektorientierten Umgebung nicht programmiert (z Java), ich bin nicht ganz oben auf die Feinheiten der Diskussion. Aber ich habe einen Singleton in PHP 4 implementiert ich es als eine Art und Weise tat einen ‚Black-Box‘ Datenbank-Handler zu erstellen, die automatisch initialisiert und habe nicht bestanden wird oben und unten Funktionsaufrufe in einem unvollständigen und etwas gebrochenen Rahmen.

einige Links von Singleton Muster gelesen, bin ich nicht ganz sicher, ob ich es in genau der gleichen Weise wieder implementieren würde. Was war wirklich braucht, waren mehrere Objekte mit gemeinsam genutzten Speicher (zum Beispiel des eigentliche Datenbank-Handle), und das ist ziemlich viel, was mein Ruf verwandelte sich in.

Wie die meisten Muster und Algorithmen, mit einem Singleton ‚nur weil es cool ist‘ ist die falsche Sache zu Do. Ich brauchte eine wirklich ‚Black-Box‘ Ruf, die viel wie ein Singleton aussehen passiert ist. Und IMO ist, dass die Art und Weise, die Frage zu lösen. Beachten Sie die Muster, sondern auch sehen, es ist weiter gefasst und auf welcher Ebene es Instanz eindeutig sein muss,

Was meinst du, was sind meine Techniken, es zu vermeiden?

Um „zu vermeiden“ es, dass, dass es impliziert gibt viele Situationen, in denen ich begegnen, in dem das Singletonmuster ist eine natürlich gute Passform, und damit, dass ich einige Maßnahmen zu ergreifen, um diese Situationen zu entschärfen.

Es gibt aber nicht. Ich habe nicht das Singletonmuster zu vermeiden. Es ist einfach nicht entstehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top