python3基础(十二)-单例模式

1、__new__方法跟跟__init__方法是一样的,由系统解析器自动调用。而__new__方法必须要有一个返回值,是返回它的一个对象实例。

class User(object):
	def __init__(self, username, password):
		self.username = username
		self.password = password
		print("对象已经构建好了,由解释器自动回调的init方法,对象初始化")

#new方法是当对象构建的时候由解释器自动回调的方法,该方法必须返回当前类的对象,重写的是父类的静态方法
	def __new__(cls, username, password):    #如果初始化方法传入了其它参数,在这里也需要加入其它的方法
		print("User类的对象开始构建")
		return object.__new__(cls)    #如果没有返回实例,代表根本没有创建实例。

	def __str__(self):
	    return "名称:%s,密码:%s"%(self.username, self.password)

u = User("zs", "123")
print(u)

在这里插入图片描述

2、单例模式
举个常见的单例模式例子,我们日常使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此回收站是单例模式的应用。
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。
做个测试:

u1 = User("zs", "123")
u2 = User("ls", "456")
print(u1 == u2)    #==判断表达式如果返回True,这两个对象是一个对象,并且内存地址相同
print("u1对象的内存地址:%s,u2对象的内存地址:%s"%(id(u1), id(u2)))
以上结果可以看出,执行结果为False,是不同的对象。

第一种方法(伪单例模式):
如果要形成单例模式则需要在User类里面创建一个私人全局变量和一个类方法或静态方法:
__instance = None #私有全局变量,也是类属性,类属性需要通过cls类名来调用。而对象属性则是需要通过self对象来调用。

@classmethod
def get_instance(cls, username, password):    #如果对象创建时,有其它参数传入,则此函数也必须要带上其它参数
if not cls.__instance:    #判断私有变量是否为空
cls.__instance = User(cls, username, password)    #如果为空,则为私有变量重新赋值
return cls.__instance    #返回单例对象

调用方法则改为:

u1 = User.get_instance("zs", "123")    #调用类方法进行初始化
u2 = User.get_instance("ls", "456")
print(u1 == u2)    #==判断表达式如果返回True,这两个对象是一个对象,并且内存地址相同
print("u1对象的内存地址:%s,u2对象的内存地址:%s"%(id(u1), id(u2)))

注意:此种方法不能防止用户主动调用User()进行实例化。这样就会造成不是单例模式。而此处有一个优点,就是不管创建多少个对象,都是同一个对象,而此对象传入的参数,以第一次实例化对象时传入的参数为准,也就是zs和123,以后再实例化的时候传入的参数则不会被赋值到对象参数里面。

第二种方法:
原理:__new__方法就是创建类实例的方法,而且是系统自动回调,如果保证此方法返回的是同一个实例,就可以达到单例模式。

__instance = None
def __new __(cls, username ,password)
if not cls.__instance:    #判断私有变量是否为空
cls.__instance = object.__new__(cls)    #如果为空,则为私有变量重新赋值,保证object.__new__()方法只执行一次
return cls.__instance    #返回单例对象

u1 = User("zs", "123")
u2 = User("ls", "456")
print(u1 == u2)    #==判断表达式如果返回True,这两个对象是一个对象,并且内存地址相同
print("u1对象的内存地址:%s,u2对象的内存地址:%s"%(id(u1), id(u2)))

以上结果可以看出,执行结果为False,是不同的对象。
注意:此种方法的优点是,只要用户创建对象,都是同一个对象的单例模式。而里面的参数的值,刚好与第一种方法创建的单例时得到的参数值相反。因为此种方法每次实例的时候都会调用__new__方法,然后都会调用__init__方法,这就导致,每次实例化的时候,都会赋值对象参数,这就导致了每次实例化的时候,都会改变对象里面参数的值。所以对象的最终状态的参数,是以最后一次实例化时传入的参数为准。当然如果在每次调用对象前,实例化一次,则会得到刚刚传入的参数数值。
当然此种方法也不能防止用户作弊,用户也可以通过u3 = object.new(User)来获得一个对象,但是此种方法系统不会自动调用初始化方法__init__。

3、小知识:
1)、只要有默认传入的方法,就是普通的成员方法

作者:沧水巫云
博客:http://blog.csdn.NET/amir_zt/
以上原创,转载请注明出处,谢谢。
https://blog.csdn.net/amir_zt/article/details/84646228

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值