目标:
- 单例设计模式
- __new__方法
- Python中的单例
1.单例设计模式
- 设计模式:
- 设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计模式,都是针对 某一特定问题 的成熟的解决方案
- 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
- 单例设计模式
- 目的——让 类 创建的对象,在系统中只有 唯一的一个实例
- 每一次执行 类名() 返回的对象,内存地址是相同的
- 单例设计模式的应用场景
- 音乐播放 对象
- 回收站 对象
- 打印机 对象
- ········
2.__new__方法
- 使用 类名() 创建对象时,Python解释器会先调用__new__方法为对象分配空间,再调用__init__()方法初始化对象
- __new__是由object基类提供的内置的静态方法,主要作用有两个
- 在内存中为对象分配空间
- 返回对象的引用
- Python解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法
1 class MusicPlayer(object):
2 def __new__(cls, *args, **kwargs):
3 print("创建对象,分配空间")
4
5 def __init__(self):
6 print("初始化对象")
7
8 player = MusicPlayer()
9 print(player)
10 '''
11 运行结果:
12 创建对象,分配空间 :可以看出在实例化对象时,先调用了new方法为对象开辟空间
13 None :因为重写了new方法,而new方法需要将对象的地址传递给init,
14 重写时并没有做,所以没有进行初始化
15 '''
View Code
* 重写__new__方法的代码非常的固定
1.
- 一定要 return super().new(cls)
- 否则Python解释器得不到分配了空间的引用,就不会调用对象的初始化方法
- 注意:__new__是一个静态方法,在调用时需要主动传递cls参数
–
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
#创建对象时,new方法会自动被调用
print("创建对象,分配空间")
#为对象分配空间
instance = super().__new__(cls)
#返回对象的引用
return instance
def __init__(self):
print("初始化对象")
player = MusicPlayer()
print(player)
'''
运行结果:
创建对象,分配空间
初始化对象
'''
- 单例——让类创建的对象,在系统中只有唯一的一个实例
- 定义一个 类属性,初始值是None,用于记录单例对象的引用
- 重写new方法
- 如果类属性 is None,调用父类方法分配空间,并在类属性中记录结果
- 返回类属性中记录的对象引用
1 #单例设计模式
2 class MusicPlayer(object):
3 instance = None #记录对象的地址
4 def __new__(cls, *args, **kwargs):
5 #判断对象是否为空,如果为空,就为其分配地址
6 if cls.instance is None:
7 #为对象分配空间
8 cls.instance = super().__new__(cls)
9 #返回对象的引用
10 return cls.instance
11 #如果部位空,就返回第一个对象的地址
12 else:
13 return cls.instance
14 def __init__(self):
15 pass
16
17 player_1 = MusicPlayer() #
18 print(player_1)
19
20 player_2 = MusicPlayer() #
21 print(player_2)
单例设计模式案例
- 只执行一次初始化动作
- 需求:让初始化动作只被执行一次
- 解决办法
- 定义一个类属性init_flag标记是否 执行过初始化动作,初始值为False
- 在 init 方法中,判断init_flag,如果为False就执行初始化动作
- 然后将init_flag设置为True
- 这样,再次调用__init__方法时,初始化动作就不会被执行了
1 #初始化动作只执行一次
2 class MusicPlayer(object):
3 instance = None #记录对象的地址
4 init_flag = False #标记是否执行过初始化动作
5 def __new__(cls, *args, **kwargs):
6 #判断对象是否为空,如果为空,就为其分配地址
7 if cls.instance is None:
8 #为对象分配空间
9 cls.instance = super().__new__(cls)
10 #返回对象的引用
11 return cls.instance
12 #如果部位空,就返回第一个对象的地址
13 else:
14 return cls.instance
15 def __init__(self):
16 #判断初始化动作是否执行过
17 if MusicPlayer.init_flag:
18 return
19 #如果没有执行过,那么执行初始化动作
20 print("初始化播放器")
21 #修改类属性(init_flag)的标记
22 MusicPlayer.init_flag = True
23
24 player_1 = MusicPlayer() #
25 print(player_1)
26 player_2 = MusicPlayer() #
27 print(player_2)
28 player_3 = MusicPlayer() #
29 print(player_3)
30 '''
31 运行结果:
32 初始化播放器
33 34 35 36 '''
只执行一次初始化动作
"""优化后的单例设计模式"""
import threading
class MusicPlayer(object):
# 设置标记
instance = None
init_flag = None
# 创建锁对象
lock = threading.RLock()
# 构造方法
def __new__(cls, *args, **kwargs):
if cls.instance:
return cls.instance
with cls.lock:
if not cls.instance:
cls.instance = object.__new__(cls)
return cls.instance
# 初始化方法,不过初始化方法通常不需要只初始化一次下面是演示如果需要初始化一次代码应该怎么写
def __init__(self, name):
# if cls.init_flag 这样子写代码会报错,cls只能在classmethod和new中才能获取到
if MusicPlayer.init_flag:
return
with self.lock:
if not MusicPlayer.init_flag:
self.name = name
MusicPlayer.init_flag = True
a = MusicPlayer("nihao1")
b = MusicPlayer("nihao2")
c = MusicPlayer("nihao9")
print(a.name, a)
print(b.name, b)
print(c.name, c)
Original: https://www.cnblogs.com/fjfsu/p/15458718.html
Author: J.FengS
Title: 单例设计模式
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/510972/
转载文章受原作者版权保护。转载请注明原作者出处!