博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
what's the 单例模式
阅读量:5228 次
发布时间:2019-06-14

本文共 3154 字,大约阅读时间需要 10 分钟。

what's the 单例模式

  单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例

  对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

 

实现单例模式4中方式

1.文件导入

  文件导入实现单例模式的方式,主要是在一个py文件中创建要单例的类,然后实例化该类,得到该类的对象。以后调用的时候用文件导入的方式导入该对象,直接用对象.方法,无论使用该对象多少次,都只有一个实例对象在运行,即实现单例模式。

参考:django的admin和自己写的stark的site

 

2.类的方式实现(加锁是为了支持多线程)

# # 单例模式:支持多线程情况import timeimport threadingclass Singleton(object):    #创建锁,为多线程    _instance_lock = threading.Lock()    def __init__(self):        time.sleep(1)#模拟多线程阻塞    @classmethod    def instance(cls, *args, **kwargs):        # 判断进程,若省略这步直接加锁的话会使得每个进程来时无论实例化与否都加锁才验证,会造成延迟        if not hasattr(Singleton, "_instance"):            with Singleton._instance_lock:#为应对多线程加锁                if not hasattr(Singleton, "_instance"):#判断线程                    Singleton._instance = Singleton(*args, **kwargs)#实例化        return Singleton._instance#得到单例对象def task(arg):    obj = Singleton.instance()    print(obj)    #批量创建多线程for i in range(10):    t = threading.Thread(target=task,args=[i,])    t.start()time.sleep(20)#单进程obj = Singleton.instance()print(obj)#该方式的弊端:使用时必须先说明以后用单例模式时得用obj = Singleton.instance()#若公司有个小白进来用obj = Singleton()的话就不是单例了
View Code

  该方式的弊端:使用时必须先说明以后用单例模式时得用obj = Singleton.instance()若公司有个小白进来用obj = Singleton()的话就不是单例了

 

3.类中基于基于__new__方式实现 (加锁是为了支持多线程)

import timeimport threadingclass Singleton(object):    #创建锁,为多线程    _instance_lock = threading.Lock()    def __init__(self):        pass    def __new__(cls, *args, **kwargs):        #实例化时就判断        if not hasattr(Singleton, "_instance"):            with Singleton._instance_lock:                if not hasattr(Singleton, "_instance"):                    Singleton._instance = object.__new__(cls, *args, **kwargs)        return Singleton._instanceobj1 = Singleton()obj2 = Singleton()print(obj1,obj2)def task(arg):    obj = Singleton()    print(obj)for i in range(10):    t = threading.Thread(target=task,args=[i,])    t.start()# 比方式2的优点:想用实现单例模式直接用obj = Singleton()即可,再也不用担心小白乱来了
View Code

  与方式2相比的优点:想实现单例模式直接用obj = Singleton()即可,再也不用担心小白乱来了

 

4.基于metaclass的方式实现(加锁是为了支持多线程)

import threadingclass SingletonType(type):    _instance_lock = threading.Lock()    def __call__(cls, *args, **kwargs):        if not hasattr(cls, "_instance"):            with SingletonType._instance_lock:                if not hasattr(cls, "_instance"):                    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)        return cls._instanceclass Foo(metaclass=SingletonType):    def __init__(self,name):        self.name = nameobj1 = Foo('name')obj2 = Foo('name')print(obj1,obj2)# 分析:Foo类是其元类的对象,在Foo类加括号时(实例化Foo类得到obj)首先执行其元类的__call__方法,# 会判断该类是否有实例,若有的话不再创建,即完成单例模式
View Code

  分析:Foo类是其元类的对象,在Foo类加括号时(实例化Foo类得到obj)首先执行其元类的__call__方法,会判断该类是否有实例,若有的话不再创建,即完成单例模式

 

 

总结

  四种单例模式都有其一定的应用场景,都能支持多线程的情况,文件导入的形式无需加锁。一般情况下用文件导入和__new__方式实现的情况较多,在源码中基于metaclass的方式实现较少。

 

转载于:https://www.cnblogs.com/zhuminghui/p/8418978.html

你可能感兴趣的文章
SSH框架整合总结
查看>>
图的深度优先遍历
查看>>
C# 之 提高WebService性能大数据量网络传输处理
查看>>
Python面向对象之:三大特性:继承,封装,多态以及类的约束
查看>>
微信小程序实现类似JQuery siblings()的方法
查看>>
md5sum命令详解
查看>>
[bzoj1004] [HNOI2008] Cards
查看>>
使用 Swoole 来加速你的 Laravel 应用
查看>>
TextWatcher原因activity内存泄漏问题
查看>>
Merge into的使用具体解释-你Merge了没有
查看>>
Linux安装程序Anaconda分析
查看>>
如何在chrome上打开SSL3.0
查看>>
应该是实例化对象的没有对属性赋值时,自动赋值为null,但不是空指针对象引用...
查看>>
从网易与淘宝的font-size思考前端设计稿与工作流
查看>>
原生HttpClient详细使用示例
查看>>
几道面试题
查看>>
搜索引擎-SHODAN
查看>>
poj_3159_Candies
查看>>
CentOS目录结构
查看>>
网络爬虫基本练习
查看>>