单例模式是开发中最常用的一种模式,sharedPreference基本上是最常用的一种,下面就来看看单例模式的几种定义方式:
1、饿汉式单例类
饿汉式单例类是Java语言里最容易实现的单例类:
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return instance;
}
}
这个类被加载的时候,静态变量instance 就会被初始化,此时私有构造方法会被调用,单例类的唯一实例也就被创建出来了;
2、懒汉式单例类
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {
}
synchronized public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
可以看到getInstance()方法加上了synchronized 关键字进行同步,这样的目的是处理多线程环境;http://blog.csdn.net/lin_t_s/article/details/53537430这篇文章介绍了使用多进程会产生的一些异常,其中就有单例模式失效。
饿汉式单例类一旦加载就会产生类实例,而懒汉式单例类被静态加载器加载的时候是不会将自己实例化的,从资源上来讲,比饿汉式单例类稍好,从速度和反应时间来讲,比饿汉式单例类稍慢一些;
getInstance 是一个被频繁调用的方法,如果使用 synchronized 修饰 getInstance 方法后必然会导致性能下降,使用双重校验锁提升性能。
双重校验锁
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (null == instance) {
instance = new LazySingleton();
}
}
}
return instance;
}
}
3、登记式单例类
不管是饿汉式还是懒汉式单例类,他们的构造方法都是私有的,也就不能够被继承,登记式单例类也就克服了这一缺点:
父类:
package singlemodle;
import java.util.HashMap;
public class RegSingleton {
// 盛装类实例的容器
private static HashMap registry = new HashMap();
static {
RegSingleton instance = new RegSingleton();
//key未全类名
registry.put(instance.getClass().getName(), instance);
}
protected RegSingleton() {
};
public static RegSingleton getInstance(String name) {
if (name == null) {
name = "singlemodle.RegSingleton";
}
if (registry.get(name) == null) {
try {
// 通过反射得到类实例
registry.put(name, Class.forName(name).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
return (RegSingleton) registry.get(name);
}
// 测试用的方法
public static void show() {
System.out.println("我是登记单例类的父类");
}
}
子类:
package singlemodle;
public class RegSingleton_Child extends RegSingleton {
// 此处不能用private修饰,不然会报以下错误
// Class singlemodle.RegSingleton can not access a member of class
// singlemodle.RegSingleton_Child with modifiers "private"
// Constructor<T>[] constructors = privateGetDeclaredConstructors((which ==
// Member.PUBLIC));
// 通过源码可以发现构造方法必须未public修饰的
public RegSingleton_Child() {
};
public static RegSingleton_Child getInstance() {
return (RegSingleton_Child) RegSingleton.getInstance("singlemodle.RegSingleton_Child");
}
// 测试用的方法
public static void show() {
System.out.println("我是登记单例类的子类");
}
}
测试一下:
package singlemodle;
public class Test {
public static void main(String[] args) {
RegSingleton regSingleton = RegSingleton.getInstance(null);
regSingleton.show();
RegSingleton_Child regSingleton_Child = RegSingleton_Child.getInstance();
regSingleton_Child.show();
}
}
结果:
我是登记单例类的父类
我是登记单例类的子类