×

单例模式实现方式 单例模式 th

单例模式实现方式(Python如何实现单例模式)

admin admin 发表于2023-08-28 16:32:58 浏览67 评论0

抢沙发发表评论

本文目录

Python如何实现单例模式

有些时候你的项目中难免需要一些全局唯一的对象,这些对象大多是一些工具性的东西,在Python中实现单例模式并不是什么难事。以下总结几种方法:使用类装饰器使用装饰器实现单例类的时候,类本身并不知道自己是单例的,所以写代码的人可以不care这个,只要正常写自己的类的实现就可以,类的单例有装饰器保证。def singleton(cls):instances = {}def _wrapper(*args, **kwargs):if cls not in instances:instancesreturn _wrapper你会发现singleton装饰器内部使用了一个dict。当然你也可以用其他的方式,不过以下的实现是错误的:def singleton(cls):_instance = None #外部作用域的引用对于嵌套的内部作用域是只读的def _wrapper(*args, **kwargs):if _instance is None: #解释器会抛出“UnboundLocalError: ...referenced before assignment“_instance = cls(*args, **kwargs) #赋值行为使解释器将“_instance“看作局部变量return _instancereturn _wrapper使用元类(__metaclass__)和可调用对象(__call__)Python的对象系统中一些皆对象,类也不例外,可以称之为”类型对象”,比较绕,但仔细思考也不难:类本身也是一种对象,只不过这种对象很特殊,它表示某一种类型。是对象,那必然是实例化来的,那么谁实例化后是这种类型对象呢?也就是元类。Python中,class关键字表示定义一个类对象,此时解释器会按一定规则寻找__metaclass__,如果找到了,就调用对应的元类实现来实例化该类对象;没找到,就会调用type元类来实例化该类对象。__call__是Python的魔术方法,Python的面向对象是”Duck type”的,意味着对象的行为可以通过实现协议来实现,可以看作是一种特殊的接口形式。某个类实现了__call__方法意味着该类的对象是可调用的,可以想像函数调用的样子。再考虑一下foo=Foo()这种实例化的形式,是不是很像啊。结合元类的概念,可以看出,Foo类是单例的,则在调用Foo()的时候每次都返回了同样的对象。而Foo作为一个类对象是单例的,意味着它的类(即生成它的元类)是实现了__call__方法的。所以可以如下实现:class Singleton(type):def __init__(cls, name, bases, attrs):super(Singleton, cls).__init__(name, bases, attrs)cls._instance = Nonedef __call__(cls, *args, **kwargs):if cls._instance is None# 以下不要使用’cls._instance = cls(*args, **kwargs)’, 防止死循环,# cls的调用行为已经被当前’__call__’协议拦截了# 使用super(Singleton, cls).__call__来生成cls的实例cls._instance = super(Singleton, cls).__call__(*args, **kwargs)return cls._instanceclass Foo(object): #单例类__metaclass__ = Singleton》》》a = Foo()》》》b = Foo()》》》a is b》》》True》》》a.x = 1》》》b.x》》》1使用__new____init__不是Python对象的构造方法,__init__只负责初始化实例对象,在调用__init__方法之前,会首先调用__new__方法生成对象,可以认为__new__方法充当了构造方法的角色。所以可以在__new__中加以控制,使得某个类只生成唯一对象。具体实现时可以实现一个父类,重载__new__方法,单例类只需要继承这个父类就好。class Singleton(object):def __new__(cls, *args, **kwargs):if not hasattr(cls, ’_instance’):cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)return cls._instanceclass Foo(Singleton): #单例类a = 1

android 几种单例模式的写法

先不论单例模式的写法,有些方面是相同的,比如都需要将唯一的对象设置为static的,都需要将构造方法private化,代码如下:public class MyInstance { private static MyInstance instance; private MyInstance(){}}第一种:最原始的单例模式,代码如下:public static MyInstance getInstance(){ if(instance==null){ instance=new MyInstance();} return instance;}多线程并发时,可能会出现重复new对象的情况,因此不提倡使用。第二种:将整个方法块进行加锁,保证线程安全。public static synchronized MyInstance getInstance(){ if(instance==null){ instance=new MyInstance();} return instance;}这种代码下,每条线程都会依次进入方法块内部,虽然实现了单例,但是影响了运行效率,可以使用但是也不怎么提倡。第三种:进一步优化的方法。public static MyInstance getsInstance(){ synchronized (MyInstance.class){ if(instance==null){ instance=new MyInstance(); return instance;}else{ return instance;}}}这种方式只是第二种方法的一种优化,但是优化有限。(以下的几种方法比较推荐使用)第四种:双层判断加锁,效率影响小且保证了线程安全。public static MyInstance getsInstance() { if (instance == null) { synchronized (MyInstance.class) { if(instance==null){ instance=new MyInstance();}}} return instance;}这种方法是对第二种和第三种方法的进一步优化,比较推荐使用。第五种:内部类实现单例,不用线程锁来实现效率的提升。public class MyInstance { private MyInstance() {} public static MyInstance getInstance(){ return MyInstanceHolder.instance;} private static class MyInstanceHolder{ private static MyInstance instance=new MyInstance();}}在内部类中new对象,再将内部类的对象返回,这种方法是使用了java中class加载时互斥的原理来实现了线程的安全。不加线程锁也使得运行效率不会受到较大的影响。比较提倡。

如何实现单例模式

这个模式保护类的创建过程来确保只有一个实例被创建,它通过设置类的构造方法为私有来达到这个目的。 要获得类的实例,单例类可以提供一个方法,如getInstance,来返回类的实例。该方法是唯一可以访问类来创建实例的方法。 下面是单例的一个例子:Java代码publicclassSingletonPattern{privatestaticSingletonPatterninstance;privateSingletonPattern(){}publicstatic synchronized SingletonPatterngetInstance(){if(instance==null){instance=newSingletonPattern();}returninstance;}} 当我们要实现单例的时候,有如下的规则需要遵循: 从上面的示例代码中可以看出,一个单例类有一个静态的属性来保存它唯一的实例 需要将类的构造方法设置为private。这样你不允许其他任何类来创建单例类的实例,因为它们不能访问单例类的构造方法。