Python: singleton design pattern

Disclaimer: This article is a blogger original article, welcome to reprint, please indicate the source https://blog.csdn.net/mouday/article/details/91493462

Singleton:
1, to ensure that only one object class has been created and
2, provides a global access point to the object
parallel access 3, control of the shared resource

Achieve a singleton easiest way:
the privatization of the constructor, and create a static method to complete object initialization

Be used:
a class object is required only one instance

Example disadvantage single mode
1, the global variables may be erroneously modified
2, creating multiple references to the same object
3, all depend on the class of global variables are due to changes in a closely coupled as a class of global data, which may unintentionally the impact of another class

A classic singleton

Only generates a class instance Singleton

# -*- coding: utf-8 -*-


class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance


if __name__ == '__main__':
    s1 = Singleton()
    s2 = Singleton()

    print(s1)
    print(s2)
    print(s1 == s2)
    print(s1 is s2)
"""
<__main__.Singleton object at 0x1021d58d0>
<__main__.Singleton object at 0x1021d58d0>
True
True
"""

Second, lazy instantiation

The actual object creation occurs in get_instance ()

# -*- coding: utf-8 -*-


class Singleton(object):
    __instance = None

    def __init__(self):
        if not Singleton.__instance:
            print("create...")
        else:
            print("already exist...")

    @classmethod
    def get_instance(cls):
        if not cls.__instance:
            cls.__instance = Singleton()
        return cls.__instance


if __name__ == '__main__':
    s1 = Singleton.get_instance()  # 实例化

    s2 = Singleton.get_instance()  # 已存在,不会实例化

    print(s1)
    print(s2)
    print(s1 == s2)
    print(s1 is s2)
"""
create...
<__main__.Singleton object at 0x101ad5860>
<__main__.Singleton object at 0x101ad5860>
True
True
"""

Third, the single-state mode Monostate

All objects share the same state

# -*- coding: utf-8 -*-


class Borg(object):
    __data = {"age": 23}

    def __init__(self):
        self.__dict__ = self.__data


if __name__ == '__main__':
    b1 = Borg()
    b2 = Borg()

    # b1 和 b2是不同的对象,共享了相同的属性
    print(b1)
    print(b2)

    # 修改b1对象, b2对象的属性也变化了
    b1.name = "Tom"

    print(b1.__dict__)
    print(b2.__dict__)

"""
<__main__.Borg object at 0x102345f60>
<__main__.Borg object at 0x1023452e8>
{'age': 23, 'name': 'Tom'}
{'age': 23, 'name': 'Tom'}
"""

Fourth, based on single embodiment metaclass

Metaclass control class instantiation

# -*- coding: utf-8 -*-


class MetaSingleton(type):
    _instances = {}

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


class Logger(metaclass=MetaSingleton):
    pass


if __name__ == '__main__':
    logger1 = Logger()
    logger2 = Logger()

    print(logger1)
    print(logger2)

"""
<__main__.Logger object at 0x1013658d0>
<__main__.Logger object at 0x1013658d0>
"""

Fifth, a single-mode application Example

The database synchronization

# -*- coding: utf-8 -*-

class MetaSingleton(type):
    _instances = {}

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


import sqlite3


class Database(metaclass=MetaSingleton):
    connection = None

    def __init__(self, db_url):
        self.db_url = db_url

    def get_cursor(self):
        if self.connection is None:
            self.connection = sqlite3.connect(self.db_url)
            self.cursor = self.connection.cursor()

        return self.cursor


if __name__ == '__main__':
    db_url = "db.sqlite3"
    cursor1 = Database(db_url).get_cursor()
    cursor2 = Database(db_url).get_cursor()

    print(cursor1)
    print(cursor2)
"""
<sqlite3.Cursor object at 0x101b4c490>
<sqlite3.Cursor object at 0x101b4c490>
"""

Six, two single-mode application Example

Monitoring server, shared server data

# -*- coding: utf-8 -*-


class HealthCheck(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self):
        self.servers = []

    def add_server(self, server):
        self.servers.append(server)

    def pop_server(self):
        return self.servers.pop()

    def show_server(self):
        print("*" * 10)
        for server in self.servers:
            print(server)
        print("*" * 10)


if __name__ == '__main__':
    h1 = HealthCheck()

    h2 = HealthCheck()

    h1.add_server("server1")
    h1.add_server("server2")
    h1.add_server("server3")

    h2.pop_server()

    h2.show_server()
    """
    **********
    server1
    server2
    **********
    """

to sum up

1, when a class requires only one object, you can use a single embodiment mode
2, classic single embodiment mode, allowing multiple instantiated, but returns the same object
3, Borg-state mode or single Monostate share the same state allows the creation of multiple objects
4, singleton service may be applied between multiple, consistent database operation

Reference:
"Design Mode Python 2nd edition" Chapter singleton design pattern

Guess you like

Origin blog.csdn.net/mouday/article/details/91493462