单例模式

单例模式:基于某种方法实例化多次得到实例是同一个。

为什么用单例模式:当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例

# 设计模式  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)
posted @ 2019-09-04 21:30  PLPLPL  阅读(111)  评论(0编辑  收藏  举报
// 目录