目录
单例模式值类的绑定方法,装饰器方式
设计模式:
总共有23中设计模式,单例模式就是其中一个
单例模式:整个过程中只有一个实例,所有生成的实例都指向同一块内存空间
先举一个不是单例的代码
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person('fvv', 18)
p2 = Person('nick', 6666)
#输出内存地址
print(p1)
print(p2)
结果如图
从结果图可以看出这两个实例的内存地址是不一样的,不符合单例模式的要求
实现单例模式的第一种方式
第一种方式以类的绑定方法来实现
现在以下面的条件为例子来表达单例模式:
1.需求当用户端口和地址,实例化产生新对象
2.当用户不输入端口和地址,每次拿到的对象,都是同一个
略微复杂的代码能看懂就看,看不懂算,但是这个代码实现了
#需求当用户端口和地址,实例化产生新对象
#当用户不输入端口和地址,每次拿到的对象,都是同一个
class Sql():
_instance = None#这里定义了一个参数一个变量
def __init__(self, port, host):
self.port = port
self.host = host
@classmethod
def get_sigoleton(cls):
import settings#这里引用我写的模块
if cls._instance:
return cls._instance
else:
cls._instance = cls(settings.PORT, settings.HOST)
return cls._instance
s1=Sql.get_sigoleton()
s2=Sql.get_sigoleton()
print(s1)
print(s2)
来提供一个简化版
class Sql:
# 类属性,用于存储单例实例
_instance = None
def __init__(self, port, host):#port是端口号,host是主机IP地址
# 初始化数据库连接的端口和主机地址
self.port = port
self.host = host
@classmethod
def get_singleton(cls, port, host):
# 类的绑定方法,用于获取单例实例
if cls._instance is None:
# 如果单例实例为None,表示还没有创建实例
# 创建新的Sql实例,并赋值给类属性 _instance
cls._instance = cls(port, host)
# 返回已存在的单例实例
return cls._instance
# 创建两个Sql实例,但实际上它们会是同一个实例
s1 = Sql.get_singleton(3360, '127.0.0.1')
s2 = Sql.get_singleton(3360, '127.0.0.1')
# 使用 is 运算符检查它们是否是同一个实例
# 由于它们都是通过 get_singleton 方法获取的,所以会返回 True
print(s1 is s2)#结果为True
这个代码省去了引用模块的那一步,同时也更简洁了
实现单例模式的第二种方式
通过装饰器来实现单例模式
复杂版
def get_sigoleton(cls):
import settings#这里引用了
_instance = cls(settings.PORT, settings.HOST)
def wrapper(*args, **kwargs):
if len(args)!=0 or len(kwargs)!=0:
#表示传了参数,生成新对象
res = cls(*args, **kwargs)
return res
else:
return _instance
return wrapper
@get_sigoleton#会把下面的Sql当参数传入,相当于:Sql = get_sigoleton(Sql)
class Sql():
_instance = None
def __init__(self, port, host):
self.port = port
self.host = host
s1 = Sql()
s2 = Sql()
print(s1)
print(s2)
现在以生活为例子来简单实现这个装饰器实现单例模式的方式
以洗衣机为例子
# 定义一个装饰器,用于创建单例对象
def zhuangshiqi(cls):
instances = {} # 用于存储单例对象的字典
# 定义内部函数,用于创建或获取单例对象
def get_instance(*args, **kwargs):
# 如果类 cls 还没有创建单例对象,则创建并保存到 instances 字典中
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
# 如果已经存在单例对象,直接返回
return instances[cls]
return get_instance
# 使用装饰器创建单例类
@zhuangshiqi
class xiyiji:
def __init__(self, brand):
self.brand = brand
def wash(self):
print(f"{self.brand}洗衣机正在洗衣服")
# 家庭成员使用单例洗衣机
mom_washer = xiyiji("品牌X")
dad_washer = xiyiji("品牌X")
# 无论多少个家庭成员,都只有一个洗衣机
print(mom_washer is dad_washer) # 输出 True,表示两者是同一个实例对象
实现单例模式的第三种方式
通过元类来实现单例
视频里的不利于理解这里提供简单的思路点:
#第三种,通过元类
class Coff:
#使用类变量来存储唯一的咖啡店实例
_instance = None
def __new__(cls):
#如果咖啡店实例不存在,创建并返回
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.coffee_count = 0
return cls._instance
def serve_coffee(self):
self.coffee_count += 1
print(f'制作了第{self.coffee_count}杯咖啡')
#客人来到唯一的咖啡店
man1 = Coff()
man2 = Coff()
print(man1 is man2)#因为都是同一个咖啡店实例这就符合了单例模式所以返回True
#点咖啡,表示这两个客人共享同一个咖啡店的实例
man1.serve_coffee()
man2.serve_coffee()
print(man1 is man2)#这里再进行判断结果还是True
结果如图
这里的咖啡店例子也说明了我单例模式的核心
假设有一个小镇上的唯一咖啡店。无论多少人想要一杯咖啡,他们都必须去这家咖啡店。咖啡店就像一个单例,只有一个实例。
在这个场景中,咖啡店就是单例,每个人都共享这个单例。这确保了在整个小镇上只有一家咖啡店,无论多少人来喝咖啡,他们都只能去这家店。
单例模式的核心概念是:只有一个实例对象,而不管有多少人尝试访问它。
第四种方法,通过模块导入(python的模块就是单例的体现)
首先生成一个模块settings这个模块
PORT = 3360
HOST = '127.0.0.1'
class Sql():
def __init__(self, port, host):
self.port = port
self.host = host
s1 = Sql(PORT, HOST)
然后再调用这个模块
#第四种方法,通过模块导入(python的模块是天然的单例)
def test():
from settings import s1#我导入settings生成好的实例
print(s1)
def test2():
from settings import s1
print(s1)
#这些函数调用的都是同一个实例对象符合单例的想法
test()
test2()
结果如图