"""
1、单列模式是什么
列子:电脑上有一个回收站,在操作系统中,回收站只有一个实例,整个系统中唯一实例,而且是自行提供的实例,因此回收站是单例模式应用。
单列模式是指:保证一个类仅有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单列类。总线对象,就是一个单列,它仅有一个是咧,每个线程对总线的访问只有一个全局访问点,即唯一的实例。
问题,在多线程中,为了保证线程安全需要在内部加入锁
解决:为枷锁的部分并发执行,加锁的部分串行执行,速度降低,但是保证了数据的安全。
"""
# 第一个
import threading
import time
# 这里使用方法__new__来实现单列模式
#我们知道,当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.__new__),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式
class dome1(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'): # 判断该对象cls 是否包含对应属性
orig = super(dome1, cls) # 如果没有 创建继承使用super() 可以逐一调用所有的父类方法
cls._instance = orig.__new__(cls, *args, **kwargs)
return cls._instance
# 总线
class Bus(dome1):
lock=threading.RLock() # 多重锁,在同一线程中可用被多次acquire。如果使用RLock,那么acquire和release必须成对出现,调用了n次acquire锁请求,则必须调用n次的release才能在线程中释放锁对象
def sed(self,data):
self.lock.acquire()
time.sleep(4)
print("send data ...",data)
self.lock.release()
#线程对象,为更加说明单例的含义,这里将Bus对象实例化写在了run里
class Vis(threading.Thread):
my=""
name=""
def getName(self):
return self.name
def setName(self, name: str):
self.name=name
def run(self):
self.my=Bus()
self.my.sed(self.name)
if __name__=="__main__":
for i in range(10):
print("i",i)
my=Vis()
my.setName("en_i{}".format(str(i)))
my.start()
"""
运行结果如下下:
在程序运行中,9个线程同时运行,每隔4秒打印,分别占用总线程资源,虽然看上去是被实例化9次,但实际内存只有一个实例。
单例模式是所有设计模式中比较简单的一类,
其定义如下:Ensure a class has only one instance, and provide a global point of access to it.(保证某一个类只有一个实例,而且在全局只有一个访问点)
i 0
i 1
i 2
i 3
i 4
i 5
i 6
i 7
i 8
i 9
send data ... en_i0
send data ... en_i1
send data ... en_i2
send data ... en_i3
send data ... en_i4
send data ... en_i5
send data ... en_i6
send data ... en_i7
send data ... en_i8
send data ... en_i9
"""
"""
单例模式的优点:
1、由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间;
2、全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用;
3、单例可长驻内存,减少系统开销。
单例模式的应用举例:
1、生成全局惟一的序列号;
2、访问全局复用的惟一资源,如磁盘、总线等;
3、单个对象占用的资源过多,如数据库等;
4、系统全局统一管理,如Windows下的Task Manager;
5、网站计数器。
单例模式的缺点:
1、单例模式的扩展是比较困难的;
2、赋于了单例以太多的职责,某种程度上违反单一职责原则(六大原则后面会讲到);
3、单例模式是并发协作软件模块中需要最先完成的,因而其不利于测试;
4、单例模式在某种情况下会导致“资源瓶颈”。
"""