1.什么是单例模式
通过单例模式保证系统中应用该模式的的一个类只有一个对象实例.
2.为什么要用单例模式
避免对象频繁创建与销毁造成资源的浪费
代码更优雅
部分特殊场景,利于同步.维护状态
3.如何实现单例模式
构造器私有化,外部无法创建对象
自己创建唯一的实例,并暴露出提供此实例方法
保证代码的健壮
4.具体实现
1.恶汉式
`加载类的时候,初始化实例.JVM保证线程加载安全.(类加载器是线程安全的).
缺点:不管是否要使用,类加载的时候,会进行初始化.其实不使用这个类而去加载的话情况应该很少.使用静态化方法或变量?我觉得没必要.类本来就应该单一职责.访问应该也是用实例对象去访问.`
public class Singleton_01 {
/**
* 创建唯一实例
*/
private static final Singleton_01 INSTANCE = new Singleton_01();
/**
* 私有构造器
*/
private Singleton_01() {
}
/**
* 暴露出此实例
*/
public Singleton_01 getInstance() {
return INSTANCE;
}
}
2.懒汉式
public class Singleton_02 {
private static volatile Singleton_02 INSTANCE;
/**
* 私有化构造方法
*/
private Singleton_02() {
}
/**
* 在需要用到的时候再去实例化对象
* 保证线程安全
*/
public static Singleton_02 getInstance() {
/*synchronized放在这和写下面区别:写在这每次调用要加一次锁,就是每次生成对象
* 时都要在此一个个通过,而放在下面.理论上只有第一次并发生成时进入到锁,以后都直接返回
* 已经初始化的 INSTANCE
*/
if (INSTANCE == null) {
synchronized (Singleton_02.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton_02();
}
}
}
return INSTANCE;
}
}
3.静态内部类实现
public class Singleton_03 {
/**
* 私有构造器
*/
private Singleton_03() {
}
/**
* 暴露获取实例方法
*
*/
public Singleton_03 getInstance() {
return Singleton_03Holder.INSTANCE;
}
/**
* 利用静态内部类加载,只会在调用的时候加载Singleton_03Holder类
* 完成初始化.且只会调用一次
*/
private static class Singleton_03Holder {
private final static Singleton_03 INSTANCE = new Singleton_03();
}
}
4.from Effective Java
只能说牛,然后反思这本书为啥只看了一半,当然真这么写没见过也有点别扭
public enum Singleton_04 {
/**
* 不仅解决线程同步,还可防止反序列化
*/
INSTANCE;
public void method() {
// do something
}
public static void main(String[] args) {
Singleton_04.INSTANCE.method();
}
}
备注:为何说能反序列化 java可以class文件,将其load到内存,然后new出实例.前面的写法都可以通过反射创建对象.枚举单例可以防止反序列化,因为其没有构造方法