原创:花括号MC(微信公众号:huakuohao-mc),欢迎分享,转载请保留出处。
单例模式顾名思义,就是保证系统中一个类只有一个唯一的对象实例。实际开发过程中经常会碰到这种需求。
单例模式有两种实现方式,一种称为饿汉式,一种称为懒汉式。
先来看一下UML图:
饿汉式
之所以称为饿汉,是因为该种实现方式是在类被加载得时候就初始化对象,而且是通过JVM的类加载机制保证系统中只有一个类实例。
先看饿汉式的完整代码
public class SingleObject {
//create an object of SingleObject
private static SingleObject instance = new SingleObject();
//make the constuctor private so that this class cannot be instantiated
private SingleObject(){}
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("I'm eager");
}
}
饿汉式的关键代码在第一行,通过static关键字修饰了instance变量了,这样在类被加载的时候就会初始化SingleObject。
懒汉式
所谓的懒汉式就是在需要的时候在创建对象,懒汉式比较复杂,需要通过锁加双重检查机制来保障多线程环境下,只有一个实例被创建。 完整代码如下
public class LazySingleObject {
private volatile static LazySingleObject instance = null;
private LazySingleObject() {}
public static LazySingleObject getInstance(){
//第一重检查
if (instance == null){
synchronized (LazySingleObject.class){
//第二重检查
if (instance == null){
instance = new LazySingleObject();
}
}
}
return instance;
}
public void showMessage(){
System.out.println("I'm lazy");
}
}
这样使用单例模式
SingleObject object = SingleObject.getInstance();
//show the message
object.showMessage();
总结
单例模式也是创建型模式之一,实现该模式的时候都要把实例变量设置为静态的,其次构造函数都要变成私有的,防止在外部被引用并创建对象。饿汉式实现起来比较容易,但是初始化的实例对象比较耗时和占用资源的话,在系统启动时会比较浪费时间和资源;相反懒汉式则是在需要的时候进行初始化,不会占用系统启动资源,但是实现起来比较麻烦,特别是在多线程的场景下,除非有特殊要求,否则建议使用饿汉式。
推荐阅读