单例模式
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, 一次创建,永远不会再被修改