Implementieren Sie das Singleton-Muster in Python

Singleton-Muster

Singleton ist eines der Entwurfsmuster, mit denen eine Klasse nur ein Instanzobjekt haben kann. Wenn Sie dies beispielsweise verwenden, indem Sie eine Klasse für die Verbindung mit der Datenbank erstellen, können Sie Code unter der Annahme schreiben, dass mehrere Instanzen die Datenbank nicht gleichzeitig betreiben, sodass Sie Synchronisation und Daten im Speicher verwalten können. Sie werden in der Lage sein. Dies erleichtert auch die Steuerung der Parallelität. Wenn Sie beispielsweise ein Dokument haben, das eine eindeutige Dokument-ID reserviert, ist es besser, ein Dienstprogramm zu haben, um die Arbeit zu erledigen. Daher ist es besser, das Singleton-Muster zu übernehmen.

So überschreiben Sie die Methode new () `

Sie können die Methode new () `überschreiben und wie folgt implementieren:

class Singleton(object):
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)
            
        return cls._instance

Erstellen Sie mehrere Instanzen aus dieser Klasse und überprüfen Sie die ID. Sie können sehen, dass dasselbe Objekt erstellt wurde.

obj1 = Singleton()
obj2 = Singleton()

print(id(obj1) == id(obj2))
# True

print(obj1 == obj2)
# True

Diese Methode weist jedoch einige Fallstricke auf. Erstellen Sie Unterklassen, die von dieser Klasse erben, und erstellen Sie jeweils Instanzen.

class SubSingleton(Singleton):
    pass

print(Singleton())
# <__main__.Singleton object at 0x10cfda9e8>

print(SubSingleton())
# <__main__.Singleton object at 0x10cfda9e8> 

Bei Betrachtung dieses Ergebnisses wird die Unterklasseninstanz als Instanz der Basisklasse erstellt. Darüber hinaus besteht das Problem, dass sich das Verhalten in Abhängigkeit von der Reihenfolge ändert, in der die Instanzen erstellt werden.

class SubSingleton(Singleton):
    pass

print(SubSingleton())
# <__main__.SubSingleton object at 0x10c3f57b8>

print(Singleton())
# <__main__.Singleton object at 0x10c3f5748> 

Wenn das Verhalten je nach Reihenfolge unterschiedlich ist, ist es schwierig, das Verhalten vorherzusagen. Insbesondere für große Anwendungen wird das Debuggen schwierig. Dies liegt daran, dass die Anwendung abhängig von den Aktionen des Benutzers und der Reihenfolge des Imports zerstört werden kann. Im Allgemeinen sollten Sie vermeiden, die Singleton-Klasse zu erben und zu verwenden. Die Methode zum Überschreiben der Methode new () `ist ebenfalls eine sichere Implementierung, sofern Sie keine Unterklassen erstellen. In einigen Sprachen, z. B. in C #, können Sie die Vererbung mithilfe des versiegelten Modifikators verbieten. Python kann die Vererbung jedoch nicht verbieten und kann falsch implementiert werden. Daher ist es sicherer, den Fall der Vererbung zu betrachten.

Verwendung der Metaklasse

Sie können eine Klasse Singleton erstellen, indem Sie die Methode call () der Metaklasse überschreiben.

class MetaSingleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class Singleton(metaclass = MetaSingleton):
    pass

class SubSingleton(Singleton):
    pass

print(Singleton() == Singleton())
# True

print(SubSingleton() == SubSingleton())
# True

print(Singleton())
# <__main__.Singleton object at 0x10ce84ef0>

print(SubSingleton())
# <__main__.SubSingleton object at 0x10ce84e48>
#Versuchen Sie, die Generierungsreihenfolge umzukehren
print(SubSingleton())
# <__main__.SubSingleton object at 0x10ce84c18>

print(Singleton())
# <__main__.Singleton object at 0x10ce84cf8>

Wenn Sie die obige Implementierung überprüfen, wird aus jeder Klasse nur eine Instanz generiert, und Sie können sie unabhängig von der Generierungsreihenfolge implementieren. Dies ist also besser als die Methode zum Überschreiben der Methode "new ()". Ich denke es ist sicher.

Implementierung durch Borg zu ersetzen

Diese Methode wurde von Alex Martelli, dem Autor von "Python Cookbook", vorgeschlagen. Es verhält sich wie ein Singleton, jedoch mit einer anderen Struktur, sodass __dict__ alle Klasseninstanzen gemeinsam nutzt. Dies nennt man Borg oder Monostate.

class Borg(object):
    _state = {}
    def __new__(cls, *args, **kwargs):
        ob = super().__new__(cls, *args, **kwargs)
        ob.__dict__ = cls._state
        return ob

print(Borg() == Borg())
# False

Durch das Erstellen mehrerer Borg-Klassen werden unterschiedliche Instanzen erstellt. Es kann jedoch als Alternative zu Singleton verwendet werden, da sich mehrere Instanzen so verhalten, als wären sie eine. Singleton garantiert eine Instanz, aber was noch wichtiger ist, es garantiert ein Verhalten. Borg, das die Einzigartigkeit des Verhaltens garantieren kann, ist also eine Alternative zu Singleton. Diese Methode hat jedoch auch eine Falle. Sie können das Problem lösen, das Sie in die Unterklasse einfügen können, dies hängt jedoch von der Implementierung der Unterklasse ab. Wenn Sie beispielsweise "getattr" überschrieben haben, um Attribute mit "." In einer Unterklasse abzurufen, funktioniert Borg nicht ordnungsgemäß.

Prägnante Umsetzung

Bisher haben wir verschiedene Methoden eingeführt, aber die einfachste Methode besteht darin, ein Modul mit Funktionen vorzubereiten. Weil Python-Module ursprünglich Singleton-Objekte sind. Die obige Implementierungsmethode ist erforderlich, wenn Sie ein Framework wie Java verwenden. Daher denke ich nicht, dass das Singleton-Muster notwendig ist, es sei denn, es gibt besondere Umstände.

Referenz

--Expert Python Programming Revised 2nd Edition

Recommended Posts

Implementieren Sie das Singleton-Muster in Python
Singleton-Muster in Python
Lernen Sie das Entwurfsmuster "Prototype" mit Python
Lernen Sie das Entwurfsmuster "Builder" mit Python
Lernen Sie das Designmuster "Flyweight" in Python
Lernen Sie das Entwurfsmuster "Observer" in Python
Lernen Sie das Entwurfsmuster "Memento" mit Python
Lernen Sie das Entwurfsmuster "Befehl" in Python
Lernen Sie das Entwurfsmuster "Besucher" mit Python
Lernen Sie das Entwurfsmuster "Bridge" mit Python
Lernen Sie das Entwurfsmuster "Mediator" mit Python
Lernen Sie das Designmuster "Decorator" mit Python
Lernen Sie das Entwurfsmuster "Iterator" mit Python
Lernen Sie das Entwurfsmuster "Strategie" mit Python
Lernen Sie das Entwurfsmuster "Composite" mit Python
Lernen Sie das Entwurfsmuster "Singleton" mit Python
Lernen Sie das Entwurfsmuster "State" in Python
Lernen Sie das Entwurfsmuster "Adapter" mit Python
Singleton-Muster in Java
Besuchermuster in Python
Implementieren Sie XENO mit Python
Implementieren Sie sum in Python
Implementieren Sie Traceroute in Python 3
Lernen Sie das Entwurfsmuster "Abstract Factory" mit Python
Lernen Sie das Entwurfsmuster "Vorlagenmethode" in Python
Lernen Sie das Entwurfsmuster "Factory Method" in Python
Finde Fehler in Python
Implementieren Sie Naive Bayes in Python 3.3
Implementieren Sie alte Chiffren in Python
Implementieren Sie Redis Mutex in Python
Implementieren Sie die Erweiterung in Python
Implementieren Sie schnelles RPC in Python
Implementieren Sie den Dijkstra-Algorithmus in Python
Implementieren Sie den Slack Chat Bot in Python
Lernen Sie das Entwurfsmuster "Chain of Responsibility" in Python
Implementieren Sie die Lösung der Riccati-Algebra in Python
Implementieren Sie das Stacking-Lernen in Python [Kaggle]
Implementieren Sie die Funktion power.prop.test von R in Python
Abrufen der arXiv-API in Python
Python im Browser: Brythons Empfehlung
Speichern Sie die Binärdatei in Python
Python Singleton
Klicken Sie in Python auf die Sesami-API
Holen Sie sich den Desktop-Pfad in Python
Holen Sie sich den Skriptpfad in Python
Klicken Sie auf die Web-API in Python
Ich habe versucht, die Mail-Sendefunktion in Python zu implementieren
Ich habe die Warteschlange in Python geschrieben
Berechnen Sie den Vormonat in Python
Untersuchen Sie die Klasse eines Objekts mit Python
Holen Sie sich den Desktop-Pfad in Python
Implementieren Sie die REST-API schnell in Python
Holen Sie sich den Hostnamen in Python
Greifen Sie mit Python auf die Twitter-API zu
Der erste Schritt von Python Matplotlib
Ich habe den Stack in Python geschrieben
Beherrsche das schwache Ref-Modul in Python
Ist es überhaupt möglich, das Gesetz der Abhängigkeitsumkehr (DIP) in Python zu realisieren?
Laden Sie das Remote-Python-SDK mit IntelliJ