设计模式之单例模式

单例模式

一个类只能生成唯一一个实例对象的设计模式

为了实现这一目标,需要我们:

  1. 将类的构造器私有化,这样就不能被其他方法调用
  2. 提供一个获取该类实例变量的方法,该方法必定是公有静态的(因为此时我们还不能获得该类的实例对象,只能通过类名.方法调用)
  3. 该类自己创建自己的唯一实例,这个实例是静态私有

实现方式

单例模式有三种实现方法:

  • 懒汉式:顾名思义,在调用的时候才会创建实例对象
/**
 * 懒汉模式
 * 1.构造器私有化
 * 2.创建一个本类的静态私有变量,初始化为null
 * 3.给外部提供一个获取该变量的静态公共方法
 */
class MyJvm{
    private static MyJvm instance = null;
    private MyJvm() {}
    public static MyJvm getInstance() {
        if(null == instance) {
            instance = new MyJvm();
        }
        return instance;
    }
}

上面的懒汉式方法有一个问题,就是当有多个线程调用的时候,会不再“单例”。
折中的办法是使用synchronized方法来使之线程安全。

//线程安全的懒汉式
class MyJvm1{
    private static MyJvm1 instance = null;
    private MyJvm1() {}
    public static MyJvm1 getInstance() {
        if(null == instance) {        //double check提高效率
            synchronized(MyJvm1.class) {    //线程安全
                if(null == instance) {
                    instance = new MyJvm1();
                }
            }
        }
        return instance;
    }
}
  • 饿汉式:在类加载的时候就创建实例对象,此时不存在线程不安全的问题
/**
 * 饿汉式
 * 1.构造器私有化
 * 2.创建一个本类的静态私有变量,并初始化
 * 3.给外部提供一个获取该变量的静态公共方法
 */
class MyJvm2{
    private static MyJvm2 instance = new MyJvm2();
    private MyJvm2() {
    }
    public static MyJvm2 getInstance() {
        return instance;
    }
}
  • 内部类式:综合了懒汉式和饿汉式的实现方法,使之既能做到使用时实例化对象,并且线程安全
/**
 * 内部类式,延缓加载时间
 */
class MyJvm3{
    public static class MyJvm3Handler {
        private static MyJvm3 instance = new MyJvm3();
    }
    private MyJvm3() {
    }
    public static MyJvm3 getInstance() {
        return MyJvm3Handler.instance;
    }
}

使用时

/**
  * 测试类
  */
public class Singleton {
    public static void main(String[] args) {
        MyJvm1 m1 = MyJvm1.getInstance();
        MyJvm2 m2 = MyJvm2.getInstance();
        MyJvm3 m3 = MyJvm3.getInstance();
        
        System.out.println(m1);
        System.out.println(m2);
        System.out.println(m3);
    }
}

运行结果
单例模式