五种单例模式

单例模式:多次实例化指向同一个对象的模式

1,用类的属性存储实例化状态,实现单例

import settings


class MySQL:
    __instance = None # 原始状态设为None

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def from_conf(cls):
        if cls.__instance is None: #如果是第一次实例化,则存储实例化对象
            cls.__instance = cls(settings.IP, settings.PORT)
        return cls.__instance # 如果不是,则直接返回已存储的实例化对象
 
obj1 = MySQL.from_conf()
obj2 = MySQL.from_conf()
obj3 = MySQL.from_conf()
# obj4=MySQL('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
# print(obj4)

2,用装饰器装饰类,实现单例

import settings


def singleton(cls):
    _instance = cls(settings.IP, settings.PORT) # 在作用域实例化对象,准备被调用

    def wrapper(*args, **kwargs):
        if len(args) != 0 or len(kwargs) != 0: # 如果传入值,则重新实例化
            obj = cls(*args, **kwargs)
            return obj
        return _instance # 如果不传值,则直接返回作用域内的实例化对象

    return wrapper


@singleton  # MySQL=singleton(MySQL) #MySQL=wrapper
class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


# obj=MySQL('1.1.1.1',3306) #obj=wrapper('1.1.1.1',3306)
# print(obj.__dict__)

obj1 = MySQL()  # wrapper()
obj2 = MySQL()  # wrapper()
obj3 = MySQL()  # wrapper()
obj4 = MySQL('1.1.1.3', 3302)  # wrapper('1.1.1.3',3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

3,用元类控制类的调用,实现单例

import settings


class Mymeta(type):
    def __init__(self, class_name, class_bases, class_dic):
        # self=MySQL这个类
        self.__instance = self(settings.IP, settings.PORT)

    def __call__(self, *args, **kwargs): # 调用类时触发
        # self=MySQL这个类
        if len(args) != 0 or len(kwargs) != 0: # 如果传值,则新实例化对象
            obj = self.__new__(self)
            self.__init__(obj, *args, **kwargs)
            return obj
        else:
            return self.__instance # 如果没有传值,则使用元类中实例化好的对象


class MySQL(metaclass=Mymeta):  # MySQL=Mymeta(...)
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


obj1 = MySQL()
obj2 = MySQL()
obj3 = MySQL()
obj4 = MySQL('1.1.1.3', 3302)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

4,用模块导入的方式实现单例(模块导入只会导入一次,因此导入的对象不会再变化)\

模块中定义好的类与对象:
import settings


class MySQL:
    print('run....')

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


instance = MySQL(settings.IP, settings.PORT)
分别导入:
def f1():
    from singleton import instance
    print(instance)


def f2():
    from singleton import instance, MySQL
    print(instance)
    obj = MySQL('1.1.1.3', 3302)
    print(obj)


f1()
f2()

5,安全的单例模式

前四种单例模式都提供了生成新对象的接口,这种单例模式只会使用一个对象,不会再生成新对象
这种单例模式较为安全,反复生成的对象是同一个

class MySQL:
	# __instance = None 也可以使用这种方法
	def __new__(cls,*args,**kwargs):
		if not hasattr(cls,'instance'):
			cls.instance = super().__new__(cls) # 实例化过程丢在单例处理里面,保证了单例的唯一性
			cls.instance.ip = '127.0.0.1'
		return cls.instance
		# if cls.__instance == None:
		# 	cls.__instance = super().__new__(cls)
		# return cls.__instance
		
	# 单例内部对象属性的实例化操作一般不再交给init方法完成
	def __init__(self):
		pass


m1 = MySQL()
print(m1.ip)
m2 = MySQL()
print(m2.ip)
m3 = MySQL()
m3.ip = '192.168.0.1'
print(a3.ip)
print(a2.ip)
print(a1.ip)
m4 = MySQL()
print(a4.ip)
print(a3.ip)
print(a2.ip)
print(a1.ip)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值