1 懒汉式单例模式
与饿汉式单例模式相同的是,类的构造函数也是私有的,不同的是懒汉式单例类在第一次被引用时才将自己实例化,
1.1懒汉式单例模式:
懒汉式单例模式是UML图如下:
图1.1
从图中可以看出,和饿汉式单例模式一样它自己将自己实例化,不同的是懒汉式单例类的成员变量不再被final修饰,并且初始值为null,并且里面的静态工厂方法多了synchronized修饰符修饰。
1.2懒汉式单例模式的实现(建一个Singleton包,所有程序放在该包下):
(1)建一个需要单例化的类(LazySingleton.java)。
package Singleton;
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){}
//静态工厂方法
public synchronized static LazySingleton getInstance(){
if(instance==null){
instance=new LazySingleton();
}
return instance;
}
}
从代码可以看出,懒汉式单例类的构造方法也是私有的,所以不能在外面调用创建实例,同时该类也不能被继承。这个类的实例在第一次被引用的时候才会被创建出来,并且对静态工厂方法getInstance()做了同步化的处理,是为了防止多个线程同时调用产生多个实例。
(2)编写测试类(TestLazySingleton.java)。
package Singleton;
public class TestLazySingleton {
public static void main(String[] args) {
// TODO 自动生成方法存根
LazySingleton lazySingleton1=LazySingleton.getInstance();
LazySingleton lazySingleton2=LazySingleton.getInstance();
LazySingleton lazySingleton3=LazySingleton.getInstance();
System.out.println(lazySingleton1);
System.out.println(lazySingleton2);
System.out.println(lazySingleton3);
}
}
输出结果:
Singleton.LazySingleton@c17164
Singleton.LazySingleton@c17164
Singleton.LazySingleton@c17164
从结果可以看到,无论创建多少次,都是唯一一个实例。
(3)最后我们看一下UML图。
1.3 饿汉式单例与懒汉式单例的比较
(1) 从资源利用效率角度看,饿汉式单例模式比懒汉式单例模式差,因为饿汉式单例模式在类加载的时候都将自己实例化,多次加载就会造成多次实例化。
(2) 从反应速度的角度看,饿汉式比懒汉式速度高,而且懒汉式单例还做了同步的处理,如果在多线程的环境,耗时可能更多。
(3) 饿汉式单例模式本身更加符合Java的语言特点,比如c++语言是不容易实现,因为静态初始化在c++里面没有固定的顺序,因而在饿汉式单例类里面的instance变量的初始化与类的加载顺序没有保证,可能会出问题。
(4)以上两种单例形式因为构造方法的私有化,使得类失去了多态性,不允许被继承。为了克服这种缺点,有一种灵活的调整方法,就是把构造函数设置为受保护的,这种方式又称为登记式单例,将在下篇文章进行分析。
Author: Piano
Introduction: 师者
Sign: 前事之不忘,后事之师