Learn design patterns in 3 minutes - singleton pattern

►Single case mode

►Usage scenarios

When writing software, for some classes it is important to have only one instance. For example, there can be multiple printing tasks in a system, but there can only be one working task; a database can be queried multiple times in a system, but only one connection is required, instead of re-creating a connection for each query, because of duplication Creating a database connection wastes memory resources. Therefore, in this case, it is very important to ensure the uniqueness of an object in the system, that is, there can only be one instance of a class.

How to ensure that a class has only one instance and is easily accessible? Defining a global variable ensures that the object is always accessible, but does not prevent multiple objects from being instantiated. A better solution is to make the class itself responsible for saving its only instance. This class guarantees that no other instances are created, and it provides a method to access the instance. This is the usage scenario of singleton pattern.

►python implementation

There are many ways to implement the singleton pattern in python. Commonly used methods are as follows:

Rewrite __new__

When a class is instantiated, the __new__ method is called to create an object, so you only need to control the __new__ method to create an object so that only one instance is generated.

class DB:
    instance = None
 
 
    def __new__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super().__new__(cls, *args, **kwargs)
        return cls.instance
db1 = DB()
db2 = DB()
print(db1)
print(db2)

 The result of running the code is as follows:

<__main__.DB object at 0x000001BD06E55F70>
<__main__.DB object at 0x000001BD06E55F70>

►Decorator

Save the only instance of the class on the class attribute, and then use the class decorator to check this attribute during instantiation to control the generation of only one instance.

def single_obj(cls):
    def wrapper(*args, **kwargs):
        if cls.instance is None:
            cls.instance = cls(*args, **kwargs)
        return cls.instance
    return wrapper
 
@single_obj
class DB:
    instance = None
 
db1 = DB()
db2 = DB()
print(db1)
print(db2)

 The result of running the code is as follows:

<__main__.DB object at 0x000001E485395970>
<__main__.DB object at 0x000001E485395970>

►Metaclass

Metaclass in Python is a class used to create class objects. When a class object creates an instance object, it will definitely call the __call__ method. Therefore, rewrite the __call__ method of the metaclass to ensure that only one instance is created when calling __call__. Can.

class SingleObj(type):
    def __call__(cls, *args, **kwargs):
        if getattr(cls, 'instance', None) is None:
            cls.instance = super().__call__(*args, **kwargs)
        return cls.instance
 
class DB(metaclass=SingleObj):
    pass
 
db1 = DB()
db2 = DB()
 
print(db1)
print(db2)

The result of running the code is as follows:

<__main__.DB object at 0x00000252D5AE4F70>
<__main__.DB object at 0x00000252D5AE4F70>

Finally, I would like to thank everyone who reads my article carefully. Reciprocity is always necessary. Although it is not a very valuable thing, if you can use it, you can take it directly:

Guess you like

Origin blog.csdn.net/qq_73332379/article/details/133440181