python3的单例设计模式

单例模式

1、单例是什么

举个常见的单例模式例子,我们日常使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此回收站是单利模式的应用

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类,单例模式是一种对象创建型模式。

2、创建单例 - 保证只有1一个对象

class User:
    __instance = None

    def __init__(self, name):  

        self.name = name

    @classmethod
    def get_instance(cls, name):

        if not cls.__instance: # 如果__instance 为None

            cls.__instance = User(name)

        return cls.__instance


u1 = User.get_instance("zs")

u2 = User.get_instance("ls")

print(u1 == u2)

print("u1对象的内存地址:%s" % id(u1))

print("u2对象的内存地址: %s" % id(u2))


# 结果

# True

# u1对象的内存地址:3087472796896

# u2对象的内存地址: 3087472796896

这种写法的缺点:

    第一,当我们得进行传参得时候我们第一次传参是"zs",第二次调用的时候传参是"ls",两者都是通过User.get_instance方法获得单例,获得对象的内存地址都是一样的,而且self.name都是"zs"。

    第二,这种写法无法保证一些吃饱了撑的程序员,会 u3 =User("eg"),这样再去实例化 一个新的对象,因为在python里面无法把内置的函数设置为私有的方法


class User:
    __instance = None

    def __init__(self, name):  
        self.name = name

    @classmethod
    def get_instance(cls, name):
        if not cls.__instance: # 如果__instance 为None
            cls.__instance = User(name)
        return cls.__instance


u1 = User.get_instance("zs")
u2 = User.get_instance("ls")
print(u1 == u2)
print("u1对象的内存地址:%s" % id(u1))
print("u2对象的内存地址: %s" % id(u2))

# 结果
# True
# u1对象的内存地址:3087472796896
# u2对象的内存地址: 3087472796896
print("u2对象的内存地址: %s" % id(u2)) # u2对象的内存地址: 2498977866920

缺点:

    虽然保证了地址相同,解决了吃饱了撑的程序员创建新的实例对象,但是仍旧是吃饱了撑的程序员去传参,破坏了单例的数据

    譬如u1和u2他们传参不同,这种单例就以后者为优先,后者会改变前者的,这就违背了单例的设计原则

下面的这种单例模式就很好的解决了这种问题


class User:
    __instance = None 
    __flag = False    # 判断我是否要实例化数据

    def __init__(self, name):

        if not User.__flag:

            self.name = name

            User.__flag = True

    def __new__(cls, name):

        if not cls.__instance: # 保证object.__new__()方法只会调用一次

            cls.__instance = object.__new__(cls)

        return cls.__instance


u1 = User("zs")

u2 = User("ls")

print(u1.name) # 结果是zs

print(u2.name) # 结果是zs


print(u1 == u2) # True

print("u1对象的内存地址:%s" % id(u1)) # u1对象的内存地址:2498977866920

print("u2对象的内存地址: %s" % id(u2)) # u2对象的内存地址: 2498977866920

优点:无论我怎么修改我的name, 一次创建,永远不会再被修改

发布了23 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/TanJiaLiang_/article/details/100061963