【Java】设计模式之单例模式
工作有几年了,但是好多东西感觉没有沉淀下来,设计模式平时都在用,一些代码的技巧都是通过经验累积起来的,但是总感觉缺少一定的体系。很多东西会写,但是不会说,这就很尴尬。所以很多东西都要适当的整理一下,理论还是不能缺少的。比方说有人问你java特性,但是有的时候你可能一瞬间真的就卡住了,没办法通过专业名词表达出来。最近下定决心,花几个月的时间,把java的设计模式都整理出来。今天先整理一个个人认为大家都在用,而且比较经典的单例模式。不足之处欢迎大家指出,共同进步!∩▂∩站在巨人的肩膀上不停进步,哈哈。
UML类图
image.png单例模式
双重检查加锁单例
如果性能是你关注的重点,这个做法可以大大地减少getInstance()的时间消耗。
因为这种方法并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查,进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
public class Singleton {
//volatile关键词确保:当uniqueInstance变量被初始化成Singleton实例时,多线程正确处理uniqueInstance变量
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if (uniqueInstance == null){
synchronized (Singleton.class){
if (uniqueInstance ==null){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
静态单例
这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。
public class Singleton {
private Singleton(){}
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 类级内部类相当于其外部类的成员,只有在第一次被使用的时候才被会装载
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
枚举单例
单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化。这种方法的单例被认为是最好的单例。
public enum SingletonSourceEnum {
INSTANCE;
private Singleton1 singleton1;
private SingletonSourceEnum() {
singleton1 = new Singleton1();
}
public Singleton1 getInstance() {
return singleton1;
}
}
public class Singleton1 { }
验证方式如下:system.out输出的是true,结果表明两次获取的是一次实例
Singleton1 singleton1 = SingletonSourceEnum.INSTANCE.getInstance();
Singleton1 singleton2 = SingletonSourceEnum.INSTANCE.getInstance();
System.out.println(singleton1 == singleton2);
饿汉式单例
饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。
public class Singleton2 {
private static Singleton2 singleton = new Singleton2();
private Singleton2(){}
private static Singleton2 getInstance(){
return singleton;
}
}
懒汉式单例
懒汉式是典型的时间换空间,由于懒汉式的实现是线程安全的,这样会降低整个访问的速度,而且每次都要判断,比较浪费时间。
public class Singleton3 {
private static Singleton3 singleton ;
private Singleton3(){}
private static synchronized Singleton3 getInstance(){
if (singleton == null){
singleton = new Singleton3();
}
return singleton;
}
}
错误不足之处或相关建议欢迎大家评论指出,谢谢!如果觉得内容可以的话麻烦喜欢(♥)一下