• 单例模式


    单例模式

      (Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

    比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

    什么是单例:

      单例是指单个实例,指一个类只能有一个实例对象

    为什么要使用单例?

      当一个类的实例中的数据不会变化时使用单例,数据是不变的;在优酷系统中orm的书写有用到;

    单例模式:

      多次实例化结果指向同一个实例

    开设单例模式的方法有许多种,常用的有以下5种方式:

    第一种:基于classmethod

      .绑定到类的方法:用classmethod装饰器装饰的方法。

      特点:参数的第一个必须是cls表示当前类本身,使用类名来调用,调用时会自动传入类

    相关知识点:

    """
    1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)
    2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法
    """

    开设单例:

    class Mysql(object):
        _instance = None 单例
    
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        @classmethod
        def singleton(cls):
            if not cls._instance:
                cls._instance = Mysql('127.0.0.1', 3306)
            return cls._instance
    
    
    obj1 = Mysql.singleton()
    obj2 = Mysql.singleton()
    print(obj1)
    print(obj2)

    运行的结果:

     第二种(基于装饰器),自定义的

    def singleton(cls):
        # 该对象在类Mysql被装饰上singleton的时候就已经实例化完毕
        _instance = cls('127.0.0.1',3306)
        def inner(*args,**kwargs):
            # 判断是否传入参数,传入参数表示要实例化新的,不传表示用默认的
            if args or kwargs:
                obj = cls(*args,**kwargs)
                return obj
            return _instance
        return inner
    
    @singleton
    class Mysql:
        def __init__(self,ip,port):
            self.ip = ip
            self.port = port
    
    obj1 = Mysql()
    obj2 = Mysql()
    obj3 = Mysql()
    print(obj1,obj2,obj3)

    运行的结果是得到指向的是同一个内存地址

     第三种是基于元类的单例模式(type)

    class MymetaClass(type):
        def __call__(self, *args, **kwargs):
            if not hasattr(self,'instance'):
                self.instance = super().__call__(*args,**kwargs)
            return self.instance
    
    class Mysql(metaclass=MymetaClass):
        def __init__(self,host,port):
            self.host = host
            self.port = port
    obj = Mysql('ajdak',213)
    obj1 = Mysql('asdasdas',134234)
    print(obj,obj1)

    结果:

     第四种(基于__new__)

      元类中__new__是用于创建类对象的 ,__init__是用于初始化类的其他信息的.

    我们知道,当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.__new__),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式

    class Mysql(object):
        _instance = None
        def __init__(self,name):
            self.name = name
    
        def __new__(cls, *args, **kwargs):
            if not cls._instance:
                cls._instance = object.__new__(cls)
            return cls._instance
    
    obj = Mysql('egon')
    obj1 = Mysql('jason')
    print(id(obj),id(obj1))

    第五种(基于模块)

      其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了

    # 单独在一个py文件中定义一个类,并实例化一个对象,之后在其他文件导入这一对象,实现单例
    class Singleton(object):
        def __init__(self,host,port):
            self.host = host
            self.port = port
    
    singleton = Singleton('127.0.0.1',3306)

      

      

  • 相关阅读:
    激活函数(ReLU, Swish, Maxout)
    损失函数
    md5sum命令行使用注意事项
    Jetson ARM SeetaFace编译
    Linux下的wine生活(QQ/微信/Office)
    人脸识别引擎SeetaFace编译 ubuntu
    Python为8bit深度图像应用color map
    MySQL、MongoDB、Redis数据库Docker镜像制作
    bash的管道符与重定向
    Docker 及 nvidia-docker 使用
  • 原文地址:https://www.cnblogs.com/Gaimo/p/11628183.html
Copyright © 2020-2023  润新知