Wie kann das Proxy-Muster verwendet werden, um ein Singleton zu ersetzen?

8

Dies ist eine Reaktion auf einige Kommentare in was ist so schlimm an Singletons >

Dort wurde vorgeschlagen, dass das Proxy-Muster anstelle eines Singletons zum Zwischenspeichern von DB-Daten verwendet werden kann. Aber ich kann den Vorteil nicht sehen, und tatsächlich scheint das Singleton "kontrollierbarer" zu sein.

Lassen Sie mich auf das Problem eingehen. Angenommen, Sie haben eine Datenbank mit einer großen Menge von Daten, die sich nie ändert, so dass sie nur als schreibgeschützt betrachtet werden kann. Warum sollte das Proxy-Muster eine bessere Möglichkeit zur Modellierung dieses Daten-Caches sein als das Singleton?

(PS: Wenn du sagen willst "weil es testbarer ist!" - bitte ausführlicher, ich gewöhne mich immer noch an diese Konzepte)

Danke für Ihre Hilfe!

    
Dai Bok 19.01.2010, 15:06
quelle

3 Antworten

7

Haftungsausschluss: Ich spreche hier in Java

Singleton werden jetzt hauptsächlich als Antipattern betrachtet, weil sie in letzter Zeit häufig missbraucht wurden, da sie eine schnelle und bequeme Möglichkeit sind, Daten über die Anwendung hinweg zu teilen - was eine gewisse Überanstrengung des Entwurfsmusters darstellt eine freigegebene Ressource.

Betrachten Sie eine Programm-Standardausgabe: Der Zugriff auf diese Ressource muss durch einen einzigen Zugriffspunkt geschützt werden, um die Synchronisation der Schreibvorgänge zu ermöglichen. Aus diesem Grund haben Sie beispielsweise System.out als statische Instanz in Java.

Das Problem ist, wenn Sie anfangen, Singleton zu haben, müssen Sie alle wichtigen Details von dem, was Sie tun, wissen, weil Sie viele strenge Annahmen über Ihre Singleton-Klasse machen, die wichtigste, die es sein wird die einzige Klasse im System. Dann fangen Sie an, es zu verwenden, vorausgesetzt, es wird immer ein einziger Einstiegspunkt zu Ihrer Ressource sein, und dann tritt ein böser Fehler auf, weil Ihre Klasse nun auf einem EJB-Server implementiert wurde und jeder EJB-Kontext seinen eigenen Singleton plus einen weiteren Singleton hat jedes jsp, das vom Server neu geladen wurde, sowie ein Singleton für jedes Mal, wenn Ihr Singleton serialisiert und deserialisiert wurde (da Sie wahrscheinlich vergessen haben, die readResolve () -Methode zu überschreiben).

Deshalb müssen Singleton mit viel Sorgfalt verwendet werden und werden nun als Antipattern betrachtet, obwohl sie für ihren beabsichtigten Gebrauch völlig nützlich sind.

Im Fall eines Datenbank-Caches wäre es besser, wenn jede Klasse den Cache benötigt, der einen Proxy für diese "Cache" -Ressource verwendet. Sie können also die Logik hinzufügen, um "die Ressource zu finden" Proxy selbst, anstatt die Logik an den Abruf des Cache-Singleton gebunden zu haben, der abhängig von der Umgebung funktioniert oder nicht.

In einigen Worten ist das Verwenden von Singleton als Mittel zum gemeinsamen Zugriff auf eine Ressource schlecht, weil Sie die Methode zum Finden der Ressource (und Ignorieren der Singleton-Fallstricke) fest codieren, während Sie Singleton haben, um eine Ressource für Synchronisationszwecke zu steuern absolut akzeptabel.

denke an Semaphoren, das funktioniert nur, wenn du immer den gleichen Semaphor bekommst. In diesem letzteren Fall kann es ein Problem sein, von überall auf das Singleton zuzugreifen, um auf dieses Semaphor zuzugreifen: Hier benötigen Sie eine Klasse, um das Singleton zu umhüllen und den Lebenszyklus des Semaphors selbst genauer zu steuern.

>

proxy soll die Rolle der "Bereitstellung einer Ressource im gesamten System" abdecken, sei es eine einzelne Anwendung, ein Client-Server-System, verschiedene Komponenten des gleichen Systems und so weiter, mit dem zusätzlichen Vorteil, dass mit èrpxy die Methode der Abruf der Ressource ist undurchsichtig. Sie können ihnen ein Singleton mit einer Hash-Mappe der zwischengespeicherten Werte zur Verfügung stellen, Sie können sie auf einen Memcached irgendwo im Netzwerk zugreifen lassen, Sie können sie während der Tests einen csv lesen lassen, ohne zu ändern, wie Sie sie aus der Anwendung aufrufen / p>     

Lorenzo Boccaccia 01.02.2010, 22:31
quelle
2

Meiner Meinung nach gibt es kein "entweder oder". Eine Klasse kann mehrere Entwurfsmuster gleichzeitig implementieren. Ich würde sagen, dass die Klasse, die den Zugriff auf die externe Datenbank implementiert, in jedem Fall ein Proxy ist (in diesem Fall ein Remote-Proxy). Wenn Sie das Caching als zusätzliche Funktionalität betrachten, ist es auch ein Decorator.

Also, die wirkliche Frage ist, ob es auch ein Singleton sein soll? Nehmen wir an, es gibt genau eine externe Datenbank. Muss es nur einen CachingDBProxy geben? Ich würde sagen, es hängt von der Verwendung ab:

Wenn mehrere Clients auf ähnliche Daten zugreifen, können sie eindeutig davon profitieren, wenn sie denselben CachingDBProxy verwenden. Die von einem Client benötigten Daten könnten bereits von einem anderen Client benötigt worden sein, so dass er aus dem Cache abgerufen werden kann, anstatt einen kostspieligen Zugriff auf die Datenbank durchführen zu müssen.

Auf der anderen Seite können einige Clients auf ganz unterschiedliche Daten zugreifen. Wenn wir also davon ausgehen, dass CachingDBProxy nur eine begrenzte Menge an Datenzugriff von einer Gruppe von Clients zwischenspeichert, können Daten, die noch von einer anderen Gruppe von Clients benötigt werden, gelöscht werden, was zu einer Verschlechterung der Cache-Leistung führt. In diesem Fall kann es sinnvoll sein, mehrere CachingDBProxies zu haben, obwohl es nur eine Datenbank gibt (dies setzt natürlich voraus, dass ein gleichzeitiger Zugriff möglich ist).

Wie viele CachingDBProxies es also geben sollte, hängt von der Verwendung ab. Der CachingDBProxy sollte seine Verwendung nicht ohne Grund beschränken, daher sollte er nicht erzwingen, dass es nur eine Instanz gibt. In diesem Fall sollte CachingDBProxies kein Singleton sein, also IMHO. Nur die Clients können wissen, wie viele CachingDBProxies für sie geeignet sind.

Wenn wir andererseits einen Proxy für eine bestimmte Ressource haben, die jeweils nur einen Zugriff verarbeiten kann, muss es möglicherweise ein Singleton sein. Aber das ist ein anderer Fall als der obige Fall. Hier kommt die Anforderung direkt aus dem Bereich, für den der Proxy zuständig ist (der Zweck besteht darin, den Zugriff auf diese spezifische Ressource zu kanalisieren).

    
lwho 30.01.2010 15:47
quelle
0

Ich kann mir nur vorstellen, dass das Proxy-Muster Proxy zwischen den zwischengespeicherten Daten verwendet und die Daten lädt (alias lazy loading).

Sortieren:

%Vor%

Das hat den Vorteil, dass der Code, der dies verwendet, sich nicht darum kümmern muss, ob die Daten bereits existieren, er muss nur GetData aufrufen und fertig.

/ * Disclaimer: Code ist nicht gültig, es ist nur Pseudo nur zu Demonstrationszwecken * /

    
dbemerlin 19.01.2010 15:17
quelle

Tags und Links