单例模式

单例模式

1、什么是单例模式

  单例模式是一种设计模式

  让所有类在实例化时,指向同一个内存地址,称之为单例模式              PS:无论产生多少个对象,都会指向 单个 实例

 

  当在确定 "类中的属性与方法不变" 需要反复调用类时,会产生不同的对象,也会产生不同的内存地址,最终造成资源的浪费,如下例:

class Foo:
    def __init__(self, x, y):
        self.x = x
        self.y = y


foo_obj1 = Foo(10, 20)
print(foo_obj1.__dict__)
print(foo_obj1)

foo_obj2 = Foo(10, 20)
print(foo_obj2.__dict__)
print(foo_obj2)

  执行结果:

# foo_obj1和foo_obj2调用的属性相同,但内存地址不同
{'x': 10, 'y': 20}
<__main__.Foo object at 0x0000000001E662C8>    # foo_obj1的内存地址
{'x': 10, 'y': 20}
<__main__.Foo object at 0x0000000001E66408>    # foo_obj2的内存地址

  使用多个内存地址即浪费内存空间。 

 

 

2、单例模式的优点

  可以节省内存空间

 

 

3、单例模式实现方法

  实现方法(*****)

    1) 通过classmethod实现

    2) 通过__new__实现

    3) 通过装饰器实现

    4) 通过导入模块时实现

    5) 通过元类实现

 

1) 通过classmethod实现

  模板:

class Singleton:
    __instance = None
    @classmethod
    def singleton(cls):
        if not cls.__instance:
            cls.__instance = cls()
        return cls.__instance

# 调用阶段
obj1 = Singleton()
print(obj1)
obj2 = Singleton()
print(obj2)
obj3 = Singleton()
print(obj3)

  执行结果:

<__main__.Singleton object at 0x000001B878D24BE0>
<__main__.Singleton object at 0x000001B878D24710>
<__main__.Singleton object at 0x000001B878D53F60>

 

  例:假如数据库被多台服务器调用启动和关闭(使用classmethod实现)

class MySql:

    # 定义一个属性默认值,用于判断对象是否存在, 若对象不存在,属性值默认是None
    # __instance是类的属性
    __instance = None

    def __init__(self, host, port):
        self.host = host
        self.port = port

    @classmethod
    def singleton(cls, host, port):    # 单例方法 --> 类方法

        # 判断__instance中若没有值,证明没有对象
        if not cls.__instance:
            # 产生一个对象并返回
            obj = cls(host, port)
            # 从 None --> obj
            cls.__instance = obj

        # 若__instance有值,证明对象已经存在,则直接返回该对象
        return cls.__instance


    def start_mysql(self):
        print("启动数据库。")

    def stop_mysql(self):
        print("关闭数据库。")


HOST1 = "192.168.9.1"
PORT1 = "1532"
HOST2 = "192.168.9.2"
PORT2 = "1533"
HOST3 = "192.168.9.3"
PORT3 = "1534"
obj1 = MySql.singleton(HOST1, PORT1)
obj2 = MySql.singleton(HOST2, PORT2)
obj3 = MySql.singleton(HOST3, PORT3)


print(obj1)
print(obj2)
print(obj3)

  执行结果:

# obj1、obj2、obj3调用的属性相同,内存地址也相同
<__main__.MySql object at 0x00000000021D6D48>    # obj1的内存地址
<__main__.MySql object at 0x00000000021D6D48>    # obj2的内存地址
<__main__.MySql object at 0x00000000021D6D48>    # obj3的内存地址

  使用同一个内存地址即节省内存空间。

 

2) 通过__new__实现:通过onject的__new__方法创建空对象

  模板:

class Singleton:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            # 创造一个空对象
            cls.__instance = object.__new__(cls)
        return cls.__instance

# 调用阶段
obj1 = Singleton()
print(obj1)
obj2 = Singleton()
print(obj2)
obj3 = Singleton()
print(obj3)

  执行结果:

<__main__.Singleton object at 0x000002046AA64C88>
<__main__.Singleton object at 0x000002046AA64C88>
<__main__.Singleton object at 0x000002046AA64C88>

 

3) 通过装饰器实现

  模板:

def singleton(cls):    # cls --> Father
    _instance = {}
    def inner(*args, **kwargs):
        if cls not in _instance:
            obj = cls(*args, **kwargs)
            _instance[cls] = obj
            return _instance[cls]
    return inner

@singleton
class Father:
    pass

 

4) 通过导入模块时实现

  模板:

from Singleton import SingletonCls, obj

obj1 = SingletonCls()
obj2 = SingletonCls()
#
print(obj1)
print(obj2)
# 不变,调用的是同一个对象,所以内存地址相同
print(obj)
print(obj)

  执行结果:

<Singleton.SingletonCls object at 0x00000244AC274C50>    # obj1
<Singleton.SingletonCls object at 0x00000244AC274780>    # obj2
<Singleton.SingletonCls object at 0x00000244AC343CF8>    # obj
<Singleton.SingletonCls object at 0x00000244AC343CF8>    # obj
posted @ 2020-10-28 16:51  chchcharlie、  阅读(161)  评论(0编辑  收藏  举报