什么是单例模式:
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,系统的配置信息,在整个项目种很多地方会使用到,但是配置信息是不会在项目种被更改的,如果重复的创建配置信息的对象的化,会严重的浪费内存资源,如果能只存在一个对象,那就好了,由此而生的单例模式。
单例模式的创建有以下几个方式:
1.做成一个模块。
例:
在一个a.py文件中写好配置文件的信息的类方法,并给它创建了一个实例对象。再项目中要使用的时候,就直接 from a import singleton 把这个实例对象导进来。
class Singleton(object):
def test(self):
pass
singleton = Singleton()
2.利用装饰器。
例:
利用了下闭包。 在创建test方法的时候,执行singleton(test)语句。
外层函数调用内层函数,内层函数使用外层函数中的test对象。用一个字典instances 来判断是否已经创建了实例,若没有则创建test的实例对象,并把test类 和 test实例对象存到字典中,返回test;若已经创建,则直接返回字典中存储的test实例对象。(这里在多线程中出现资源抢夺问题,可以加锁解决。)
def singleton(cls):
instances = {}
def singleton_in(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return singleton_in
@singleton #这句话就大致可以理解 test()=singleton(test)
class test(object):
pass
a=test()
b=test()
3.重写类的__new__方法。
例:
new :必须得有一个参数,表示要实例化的类,必须得有返回值,返回值是实例化出来的实例。类被实例化时,是先执行__new__方法,再执行__init__方法,__init__方法中的self是__new__方法中返回的实例对象。
代码中用__instance的类属性做控制,这个属性存储的是第一次实例化的对象。
里面有with Singleton.__lock ,上下文资源管理器来给判断语句加上锁。这样就可防止多线程中的资源抢夺的问题,造成创建了多个实例。
class Singleton(object):
_lock = threading.Lock()
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = object.__new__(cls)
return Singleton._instance
4.利用元类机制(原理和上一种一样)
metaclass
metaclass=SingletonType这句话的意思是创建Test类用SingletonType方法来创建, 即执行SingletonType() 这个语句,调用__call__方法。
Test创建一个实例对象后,以后再创建时,只是让变量b指向实例对象的地址,也不会再执行__init__的方法,即b = Test()中 不传参数也可以执行。
import threading
class SingletonType(type):
_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
with SingletonType._lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
class Test(metaclass=SingletonType):
def __init__(self,name):
self.name = name
def single(self,aaa):
print('唱歌',aaa)
def happy(self):
print('唱歌')
a = Test('1111')
b = Test()
a.single('山无棱')
b.single('天地合')
print(id(a))
print(id(b))