设计模式--单例模式
单例模式应该算最简单的设计模式,但在Java中单例模式还是有不少坑的。
个人对单例的理解是全局中有且仅有一个的实例,不能通过其他方式构造,只能通过特定方法访问,因此单例的构造器通常是私有的,在内部会创建这个唯一实例,且会提供一个公开的方法用于访问这个实例
饿汉式
类初始化时直接加载,没有线程安全问题,但没有实现lazy loading
public class Singleton {
private static Singleton instance = new Singleton();
//私有化构造器
private Singleton() {}
//访问方法
public static Singleton getInstance() {
return instance;
}
}
懒汉式,不加锁
不加锁,在多线程环境下会new出多个对象
public class Singleton{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
懒汉式,加锁的双重校验
比较常见的一种写法,采用加锁的双重校验方式,不过个人不是很喜欢这种写法,毕竟代码比较长
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
懒汉式,静态内部类
比较喜欢这种写法,和饿汉式比较类似,但通过类加载机制避免Singleton类初始化时加载这个单例,仅在需要调用实例的时候加载
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
枚举
这个比较爽,3行代码解决,但感觉用的比较少。。
public enum Singleton {
INSTANSE
}
使用jad反编译代码可以看出枚举是在静态块中加载,属于饿汉式
package test;
public final class Singleton extends Enum
{
private Singleton(String s, int i)
{
super(s, i);
}
public static Singleton[] values()
{
Singleton asingleton[];
int i;
Singleton asingleton1[];
System.arraycopy(asingleton = ENUM$VALUES, 0, asingleton1 = new Singleton[i = asingleton.length], 0, i);
return asingleton1;
}
public static Singleton valueOf(String s)
{
return (Singleton)Enum.valueOf(test/Singleton, s);
}
public static final Singleton INSTANSE;
private static final Singleton ENUM$VALUES[];
static
{
INSTANSE = new Singleton("INSTANSE", 0);
ENUM$VALUES = (new Singleton[] {
INSTANSE
});
}
}