赞
踩
单例模式是一种应用广泛的模型,适用于一个类全局只能有一个实例的情况
比如说,在一个教学系统中定义了一个班长类,但是一个班只能有一个班长。那么需要限定一下,其他类不能随便创建班长对象,只能获取本班的班长。单例模式需要满足以下几个特征:
下面逐个分析如何达到这些特征
最简单的单例模式实现如下:
public class Singleton {
private Singleton() { //不可随意创建对象
System.out.println("创建单例模式: " + this); //测试,创建成功后输出对象哈希码
}
//饿汉式,创建后直接分配内存
private static Singleton instance = new Singleton();
//获取对象的公有接口
public static Singleton getInstance() {
return instance;
}
}
这是最简单的实现,没有考虑空间效率和线程安全
上面是饿汉式的实现过程,顾名思义,这个类是贪婪的,刚声明就把内存空间开辟后据为己有,不管此时是不是立刻就需要。那么如何让它懒一些,在需要用时再开辟空间呢?实现过程如下:
//懒汉式
private static Singleton instance = null;
public static Singleton getInstance() {
if(null == instance) instance = new Singleton();
return instance;
}
new Singleton()
从声明变量处移到getInstance()
函数中,在程序刚开始运行时,创建的只是空指针instance
,只有当外界第一次调用getInstance()
时才真正的创建。考虑节约空间资源,但是又有一个线程安全的问题
当创建饿汉式单例模式时并不会遇到这个问题,因为类的初始化是不会发生线程安全问题,但是把对象的初始化放到一个函数中时就可能出现问题
试想,一个线程查看到该对象没有被创建,于是准备着手创建,此时另一个线程也发现该对象没有被创建,都各自创建一遍,此时内存中就存在两个对象。解决这个问题可通过synchronized
关键字锁住资源,防止写冲突
//改进后线程安全的双重锁懒汉式
private volatile static Singleton instance = null; //volatile 禁止重排序,所有的写操作将在读操作以前
public static Singleton getInstance() {
if(null == instance) {
synchronized (Singleton.class) {
if(null == instance) instance = new Singleton();
}
}
return instance;
}
volatile关键字的使用很有讲究,但这个依然是不安全,于是有了下面这个终极答案:
//内部静态类实现
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
测试代码如下:
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
System.out.println("创建s1: " + s1.toString());
Singleton s2 = Singleton.getInstance();
System.out.println("创建s2: " + s2.toString());
}
这里获取了两次实例对象,看看到底是不是同一个。加上私有构造函数中同样打印输出了对象的哈希码,一共需要输出三次
单例模式的代码实现如下
class singleton(object): # 创建一个类
mysingleton = None
def __new__(self, *args, **kwargs): #重写__new__方法
if self.mysingleton is None:
self.mysingleton = object.__new__(self) #调用用object类的__new__方法创建实例
return self.mysingleton #返回实例
else:
return self.mysingleton#返回实例,与上面的返回相同
if __name__ == "__main__":
a = singleton() #实例化一个a对象
b = singleton() #实例化一个b对象
print(id(a)) #id() 函数返回对象的唯一标识符,标识符是一个整数。
print(id(b)) #如果两个一样就说明是同一个实例化对象
单例模式的使用场景例如:
import dbconfig
import pymysql
class singleton(object):
dbconn = None
def __new__(self, *args, **kwargs):
dbname=args
if self.dbconn is None:
self.dbconn = pymysql.connect(dbconfig.dbDict.get(dbname[0]), dbconfig.dbUser, dbconfig.dbPassword).cursor()
print("aaa")
return self.dbconn
else:
print("bbb")
return self.dbconn
if __name__ == "__main__":
test = singleton("ars1")
result =test.execute("select id,code from info.property where status=1")
print(test.fetchall())
print(id(test))
test1 = singleton("ars1")
result1 = test1.execute("select id,code from info.property where status=1")
print(test1.fetchall())
print(id(test1))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。