目录
设计模式简介及单例模式
1.设计模式
前人通过大量的验证创建出来解决一些问题的固定高效方法
2.IT行业
设计模式分为三大类,总共23种模式
创建型模式(5种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
3.单例模式
类加括号无论执行多少次永远只会产生一个对象
目的:
当类中有很多非常强大的方法 我们在程序中很多地方都需要使用
如果不做单例 会产生很多无用的对象浪费存储空间
我们想着使用单例模式 整个程序就用一个对象
设计模式的23种方法图如下:
单例模块实现的多种方式
方式一:绑定给类的方法
class MyClass:
__instance = None
def __init__(self,name,age):
self.name = name
self.age = age
@classmethod
def singleton(cls):
if not cls.__instance: # 判断全局的__instance是否有值
cls.__instance = cls('kimi',18)
return cls.__instance
# 1 单例模式下,执行多少次的类名加括号都只会产生一个对象
obj1 = MyClass.singleton()
obj2 = MyClass.singleton()
obj3 = MyClass.singleton()
print(id(obj1),id(obj2),id(obj3)) # 1467506641648 1467506641648 1467506641648
# 2.要是想产生新的对象,需要在类调用的时候传入新的数据
obj4 = MyClass('rose', 22)
obj5 = MyClass('kiki', 19)
print(id(obj4),id(obj5)) # 1582454534352 1582454534640
""" 这样的单例模式,扩展性更强一些"""
方式二:基于元类的类名加括号
class Mymeta(type):
def __init__(self,name,bases,dict): # 定义一个类MYsql时就触发
# 事先从配置文件种配置来造一个Mysql的实例出来
self.__instance = object.__new__(self) #产生一个对象
self.__init__(self.__instance,'kimi',18) # 给空对象初始化数据
# 上面两步可以合成下面一步
# self.__instance = super().__call__(*args,**kwargs)
super().__init__(name,bases,dict)
def __call__(self, *args, **kwargs): # Mysql(...)时触发
if args or kwargs: # 判断args or kwargs 是否有值
obj = object.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj # 传值说明我们要用新的对象
return self.__instance # 不传值说明我们要用单例的值
class Mysql(metaclass=Mymeta): #不用创建对象也能触发__init__方法,因为时元类干扰了创建类的过程。 类名加括号 触发__call__方法
def __init__(self,name,age):
self.name = name
self.age = age
# 1 单例模式下,执行多少次的类名加括号都只会产生一个对象
print(Mysql.__dict__) # {.....'_Mymeta__instance': <__main__.Mysql object at 0x00000268A06A4AF0>}
obj1 = Mysql()
obj2 = Mysql()
print(id(obj1),id(obj2)) # 1994724494064 1994724494064
# 2.要是想产生新的对象,需要在类调用的时候传入新的数据
obj4 = Mysql('rose', 25)
obj5 = Mysql('kiki', 15)
print(id(obj4),id(obj5)) # 2000220058336 2000220058288
方式三:基于模块的单例模式
"""要是通过类的方式去调,比如func1(self),说万一要传东西,而self是绑定给对象的方法,类是不能直接调的"""
>>>把下述当作模块,通过模块点obj的形式调用
'''基于模块的单例模式:提前产生一个对象 之后导模块使用'''
class C1:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def func1(self):pass
def func2(self):pass
def func3(self):pass
def func4(self):pass
obj = C1('kimi',22,'female')
# 把上述当作模块,通过模块点obj的形式调用
另一个模块去点
from django.conf import settings
方式四:定义一个装饰器实现单例模式
def singleton(cls): # cls = Mysql
__instance = cls('kimi',18)
def wrapper(*args,**kwargs): # 判断Mysql()括号里面有没有参数
if args or kwargs: #
obj = cls(*args,**kwargs)
return obj # 有值就会产生一个新的对象
return __instance # 没有值就会返回装饰器给的对象
return wrapper
@singleton # Mysql = singleton(Mysql)
class Mysql:
def __init__(self,name,age):
self.name = name
self.age = age
# 1 单例模式下,括号里面不传参数,执行多少次的类名加括号都只会产生一个对象
obj1 = Mysql()
obj2 = Mysql()
obj3 = Mysql()
print(obj3 is obj2 is obj1) # True
# 2.要是想产生新的对象,需要在类调用的时候传入新的数据
obj4 = Mysql('kiki',20)
obj5 = Mysql('rose',18)
print(obj5 is obj4) # False
方法五:基于元类
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
if not self.instance:
obj = self.__new__(self) # 创建一个空对象
self.__init__(obj) # 调用__init__给对象添加独有的数据
self.instance = obj # 创建新的对象
return self.instance # 返回类中定义好的intance
class C1(metaclass=MyMetaClass):
instance = None
obj1 = C1()
obj2 = C1()
obj3 = C1()
print(id(obj1),id(obj2),id(obj3)) # 1992688159568 1992688159568 1992688159568
# 利用反射来做
标签:__,.__,简介,self,模式,单例,Mysql,设计模式
From: https://www.cnblogs.com/zhanglanhua/p/16874499.html