单例模式
单例模式:基于某种方法实例化多次得到实例是同一个。
为什么用单例模式:当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例
# 设计模式 23种设计模式
# 单例模式:整个过程中只有一个实例,所有生成的实例都指向同一块内存空间
# class Person():
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# p1 = Person('lqz',19)
# p2 = Person('nick',18)
# print(p1)
# print(p2)
# 实现单例的第一种方法(通过类的绑定方法)
# 当用户输入端口和地址,实例化产生新对象
# 当用户不输入端口和地址,每次拿到的对象,都是同一个
class Sql():
_instance = None
def __init__(self,port,host):
self.port = port
self.host = host
@classmethod
def get_sigleton(cls):
import settings
if not cls._instance:
cls._instance = cls(settings.PORT,settings.HOST)
return cls._instance
# 每次调用get_sigleton拿到的对象都是同一个
s1 = Sql.get_sigleton()
s2 = Sql.get_sigleton()
print(s1)
print(s2)
s4=Sql('33306','192.168.1.1')
print(s4)
# 第二种:通过装饰器
# 当用户输入端口和地址,实例化产生新对象
# 当用户不输入端口和地址,每次拿到的对象,都是同一个
# def get_sigleton(cls):
# # cls就是Sql这个类
# import settings
# _instance = cls(settings.PORT,settings.HOST)
# def wraper(*args,**kwargs):
# if len(args) != 0 or len(kwargs) != 0:
# # 表示传了参数,生成新对象
# res = cls(*args,**kwargs)
# return res
# else:
# return _instance
# return wraper
def get_sigleton(cls):
_instance = None
def wrapper(*args,**kwargs):
if len(args) != 0 or len(kwargs) != 0:
# 表示传了参数,生成新对象
res = cls(*args,**kwargs)
return res
else:
import settings
nonlocal _instance
if not _instance:
_instance = cls(settings.PORT,settings.HOST)
return _instance
return wrapper
@get_sigleton #会把下面的Sql当中参数传入,相当于:Sql=get_sigleton(Sql)
class Sql():
def __init__(self,port,host):
self.port = port
self.host = host
s1 = Sql()
s2 = Sql()
s3=Sql('33306','192.168.1.1')
s4=Sql('33306','192.168.1.1')
print(s1)
print(s2)
print(s3)
print(s4)
# 第三种:通过元类
# 当用户输入端口和地址,实例化产生新对象
# 当用户不输入端口和地址,每次拿到的对象,都是同一个
class Mymeta(type):
def __init__(self,name,bases,dic):
# self是Sql类
import settings
# 把实例化好的对象,放到了类的名称空间
self._instance = self(settings.PORT,settings.HOST)
def __call__(self, *args, **kwargs):
# self是Sql类
if len(args) != 0 or len(kwargs) != 0:
obj = object.__new__(self)
obj.__init__(*args,**kwargs)
return obj
else:
return self._instance
class Sql(metaclass=Mymeta): #相当于 Sql=Mymeta(name,bases,dic) 这个会调用 Mymeta的__init__ 在里面已经向类的名称空间放了一个对象
def __init__(self,port,host):
self.port = port
self.host = host
print(Sql.__dict__)
s1 = Sql()
# 调用元类的__call__
s2 = Sql()
s3 = Sql('3306','192.0.0.1')
print(s1)
print(s2)
print(s3)
# 第四种:通过模块导入(python的模块是天然的单例)
def test1():
from sigleton import s1
print(s1)
def test2():
from sigleton import s1 as s2
print(s2)
test1()
test2()
from sigleton import s1
from sigleton import Sql
s3 = Sql('3306','192.0.0.1')
print(s1)
print(s2)
print(s3)