Was ist der Vorteil der Verwendung von Singleton anstelle von Global für Datenbankverbindungen in PHP? Ich bin der Meinung, dass die Verwendung von Singleton anstelle von Global den Code unnötig komplex macht.
Code mit Global
$conn = new PDO(...);
function getSomething()
{
global $conn;
.
.
.
}
Code mit Singleton
class DB_Instance
{
private static $db;
public static function getDBO()
{
if (!self::$db)
self::$db = new PDO(...);
return self::$db;
}
}
function getSomething()
{
$conn = DB_Instance::getDBO();
.
.
.
}
Wenn es eine bessere Möglichkeit gibt, eine andere Datenbankverbindung als global oder singleton zu initialisieren, erwähnen Sie diese bitte und beschreiben Sie die Vorteile gegenüber global oder singleton.
php
design-patterns
singleton
Imran
quelle
quelle
Antworten:
Ich weiß, dass dies alt ist, aber Dr8ks Antwort war fast da.
Wenn Sie überlegen, einen Code zu schreiben, gehen Sie davon aus, dass sich dieser ändern wird. Das bedeutet nicht, dass Sie davon ausgehen, welche Art von Änderungen irgendwann in der Zukunft vorgenommen werden, sondern dass irgendeine Form von Änderung vorgenommen wird.
Machen Sie es zu einem Ziel, das den Schmerz lindert, Änderungen in der Zukunft vorzunehmen: Ein globales Unternehmen ist gefährlich, weil es schwierig ist, es an einem einzigen Ort zu verwalten. Was ist, wenn ich diesen Datenbankverbindungskontext in Zukunft bewusst machen möchte? Was ist, wenn ich möchte, dass es sich jedes Mal, wenn es verwendet wurde, schließt und wieder öffnet? Was ist, wenn ich im Interesse der Skalierung meiner App einen Pool von 10 Verbindungen verwenden möchte? Oder eine konfigurierbare Anzahl von Verbindungen?
Eine Singleton-Fabrik bietet Ihnen diese Flexibilität. Ich habe es mit sehr wenig zusätzlicher Komplexität eingerichtet und erhalte mehr als nur Zugriff auf dieselbe Verbindung. Ich kann auf einfache Weise ändern, wie diese Verbindung später an mich weitergegeben wird.
Beachten Sie, dass ich Singleton Factory im Gegensatz zu einfach Singleton sage . Es gibt kaum einen Unterschied zwischen einem Singleton und einem globalen. Aus diesem Grund gibt es keinen Grund für eine Singleton-Verbindung: Warum sollten Sie die Zeit damit verbringen, diese einzurichten, wenn Sie stattdessen eine reguläre globale Verbindung erstellen könnten?
Was eine Fabrik Ihnen bringt, ist ein Grund, warum Sie Verbindungen erhalten, und ein separater Ort, an dem Sie entscheiden können, welche Verbindungen (oder Verbindungen) Sie erhalten.
Beispiel
class ConnectionFactory { private static $factory; private $db; public static function getFactory() { if (!self::$factory) self::$factory = new ConnectionFactory(...); return self::$factory; } public function getConnection() { if (!$this->db) $this->db = new PDO(...); return $this->db; } } function getSomething() { $conn = ConnectionFactory::getFactory()->getConnection(); . . . }
Dann, in 6 Monaten, wenn Ihre App sehr berühmt ist und durcheinander und mit einem Schrägstrich versehen wird und Sie entscheiden, dass Sie mehr als eine einzige Verbindung benötigen, müssen Sie nur ein Pooling in der Methode getConnection () implementieren. Wenn Sie sich für einen Wrapper entscheiden, der die SQL-Protokollierung implementiert, können Sie eine PDO-Unterklasse übergeben. Oder wenn Sie bei jedem Aufruf eine neue Verbindung wünschen, können Sie dies tun. Es ist flexibel statt starr.
16 Codezeilen, einschließlich geschweifter Klammern, ersparen Ihnen Stunden und Stunden und Stunden des Refactorings für etwas Unheimliches auf der ganzen Linie.
Beachten Sie, dass ich dieses "Feature Creep" nicht berücksichtige, da ich in der ersten Runde keine Feature-Implementierung durchführe. Es ist die Grenzlinie "Future Creep", aber irgendwann ist die Idee, dass "Codierung für morgen heute" immer eine schlechte Sache ist, für mich nicht lebendig.
quelle
return self::$factory->getConnection();
anstelle von verwendereturn self::$factory;
?Ich bin nicht sicher, ob ich Ihre spezifische Frage beantworten kann, wollte aber vorschlagen, dass globale / Singleton-Verbindungsobjekte möglicherweise nicht die beste Idee sind, wenn dies für ein webbasiertes System gilt. DBMS sind im Allgemeinen so konzipiert, dass sie eine große Anzahl eindeutiger Verbindungen auf effiziente Weise verwalten. Wenn Sie ein globales Verbindungsobjekt verwenden, gehen Sie wie folgt vor:
Erzwingen Sie, dass Ihre Seiten alle Datenbankverbindungen nacheinander ausführen, und beenden Sie alle Versuche, asynchrone Seiten zu laden.
Möglicherweise länger als nötig offene Sperren für Datenbankelemente halten, was die Gesamtleistung der Datenbank verlangsamt.
Maximierung der Gesamtzahl gleichzeitiger Verbindungen, die Ihre Datenbank unterstützen kann, und Verhinderung des Zugriffs neuer Benutzer auf die Ressourcen.
Ich bin sicher, dass es auch andere mögliche Konsequenzen gibt. Denken Sie daran, dass diese Methode versucht, eine Datenbankverbindung für jeden Benutzer aufrechtzuerhalten, der auf die Site zugreift. Wenn Sie nur einen oder zwei Benutzer haben, ist dies kein Problem. Wenn dies eine öffentliche Website ist und Sie Datenverkehr wünschen, wird die Skalierbarkeit zu einem Problem.
[BEARBEITEN]
In größeren Situationen kann es schlecht sein, jedes Mal, wenn Sie auf die Datenbank treffen, neue Verbindungen herzustellen. Die Antwort besteht jedoch nicht darin, eine globale Verbindung herzustellen und für alles wiederzuverwenden. Die Antwort lautet Verbindungspooling.
Beim Verbindungspooling werden mehrere unterschiedliche Verbindungen aufrechterhalten. Wenn die Anwendung eine Verbindung benötigt, wird die erste verfügbare Verbindung aus dem Pool abgerufen und nach Abschluss der Aufgabe an den Pool zurückgegeben. Wenn eine Verbindung angefordert wird und keine verfügbar ist, geschieht eines von zwei Dingen: a) Wenn die maximal zulässige Anzahl von Verbindungen nicht erreicht wird, wird eine neue Verbindung geöffnet oder b) Die Anwendung muss warten, bis eine Verbindung verfügbar ist .
Hinweis: In .NET-Sprachen wird das Verbindungspooling standardmäßig von den ADO.Net-Objekten ausgeführt (die Verbindungszeichenfolge legt alle erforderlichen Informationen fest).
Vielen Dank an Crad für den Kommentar.
quelle
Die Singleton-Methode wurde erstellt, um sicherzustellen, dass nur eine Instanz einer Klasse vorhanden ist. Aber weil die Leute es als Mittel zur Abkürzung der Globalisierung verwenden, wird es als faule und / oder schlechte Programmierung bekannt.
Daher würde ich Global und Singleton ignorieren, da beide nicht wirklich OOP sind.
Was Sie gesucht haben, ist die Abhängigkeitsinjektion .
Unter http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection finden Sie einfach zu lesende PHP-basierte Informationen zur Abhängigkeitsinjektion (mit Beispielen)
quelle
Beide Muster erzielen den gleichen Nettoeffekt und bieten einen einzigen Zugriffspunkt für Ihre Datenbankaufrufe.
In Bezug auf die spezifische Implementierung hat der Singleton den kleinen Vorteil, dass keine Datenbankverbindung initiiert wird, bis mindestens eine Ihrer anderen Methoden dies anfordert. In der Praxis macht dies in den meisten Anwendungen, die ich geschrieben habe, keinen großen Unterschied, aber es ist ein potenzieller Vorteil, wenn Sie einige Seiten / Ausführungspfade haben, die überhaupt keine Datenbankaufrufe ausführen, da diese Seiten dies nicht tun Fordern Sie jemals eine Verbindung zur Datenbank an.
Ein weiterer kleiner Unterschied besteht darin, dass die globale Implementierung möglicherweise unbeabsichtigt andere Variablennamen in der Anwendung mit Füßen tritt. Es ist unwahrscheinlich, dass Sie jemals versehentlich eine andere globale $ db-Referenz deklarieren, obwohl es möglich ist, dass Sie diese versehentlich überschreiben (sagen Sie, Sie schreiben if ($ db = null), wenn Sie if ($ db == null) schreiben wollten. Das Singleton-Objekt verhindert dies.
quelle
Wenn Sie keine dauerhafte Verbindung verwenden und es Fälle gibt, in denen dies nicht der Fall ist, finde ich einen Singleton konzeptionell schmackhafter als einen globalen OO-Entwurf.
In einer echten OO-Architektur ist ein Singleton effektiver, als jedes Mal eine neue Instanz des Objekts zu erstellen.
quelle
In dem gegebenen Beispiel sehe ich keinen Grund, Singletons zu verwenden. Als Faustregel gilt, wenn es mein einziges Anliegen ist, eine einzelne Instanz eines Objekts zuzulassen. Wenn die Sprache dies zulässt, bevorzuge ich die Verwendung von Globalen
quelle
Im Allgemeinen würde ich einen Singleton für eine Datenbankverbindung verwenden ... Sie möchten nicht jedes Mal eine neue Verbindung erstellen, wenn Sie mit der Datenbank interagieren müssen ... Dies kann die Leistung und Bandbreite Ihres Netzwerks beeinträchtigen ... Warum sollten Sie eine erstellen? neue, wenn es eine gibt ... Nur meine 2 Cent ...
RWendi
quelle
Es ist ganz einfach. Verwenden Sie niemals globales ODER Singleton.
quelle
Als Ratschlag sind sowohl Singleton als auch Global gültig und können innerhalb desselben Systems, Projekts, Plugins, Produkts usw. zusammengeführt werden . In meinem Fall mache ich digitale Produkte für das Web (Plugin).
Ich benutze nur Singleton in der Hauptklasse und ich benutze es grundsätzlich. Ich benutze es fast nicht, weil ich weiß, dass die Hauptklasse es nicht wieder instanziieren wird
<?php // file0.php final class Main_Class { private static $instance; private $time; private final function __construct() { $this->time = 0; } public final static function getInstance() : self { if (self::$instance instanceof self) { return self::$instance; } return self::$instance = new self(); } public final function __clone() { throw new LogicException("Cloning timer is prohibited"); } public final function __sleep() { throw new LogicException("Serializing timer is prohibited"); } public final function __wakeup() { throw new LogicException("UnSerializing timer is prohibited"); } }
Globale Verwendung für fast alle Sekundärklassen, Beispiel:
<?php // file1.php global $YUZO; $YUZO = new YUZO; // YUZO is name class
Zur Laufzeit kann ich Global verwenden , um ihre Methoden und Attribute in derselben Instanz aufzurufen, da ich keine weitere Instanz meiner Hauptproduktklasse benötige.
<?php // file2.php global $YUZO; $YUZO->method1()->run(); $YUZO->method2( 'parameter' )->html()->print();
Ich bekomme mit dem globalen Ziel, dieselbe Instanz zu verwenden, um das Produkt zum Laufen zu bringen, da ich für Instanzen derselben Klasse keine Factory benötige. Normalerweise ist die Instanzfactory für große Systeme oder für sehr seltene Zwecke.
In conclusion:
Wenn Sie bereits gut verstehen, dass es sich um das Anti-Pattern- Singleton handelt, und das Global verstehen , können Sie eine der beiden Optionen verwenden oder sie mischen. Wenn ich jedoch empfehle, sie nicht zu missbrauchen, gibt es viele Programmierer, die sehr außergewöhnlich und treu sind Verwenden Sie die Programmier-OOP für Haupt- und Sekundärklassen, die Sie innerhalb der Ausführungszeit häufig verwenden. (Es spart Ihnen viel CPU). 😉quelle