单例模式:保证整个系统中一个类只有一个对象的实例,实现这种功能的方式就叫单例模式
在Java中,单例模式有几种实现方式:

  1. 私有构造器
  2. 静态内部类

    1. 私有构造器

饿汉式:在类刚被加载的时候,马上就创建对象,生怕抢不到吃的

public class SingleObject {
     //在类被加载时,就创建对象
       private static SingleObject instance = new SingleObject(0);

       //私有化构造器,防止外部创建对象
       private SingleObject(int i){
              System.out.println("我是一个单例"+i);
       }

       //提供外界获取唯一对象的方法
       public static SingleObject getSingletonInstance(){
          return instance;
       }

饿汉式虽好,但是总感觉还是有点问题,因为它在类刚被加载的时候,就各种创建对象,如果我暂时还不需要的话,这样其实是会造成资源的浪费的,所以还不完美,怎么来解决这个问题呢;大家应该经常听到懒加载这个词,它的意思就是所有的事情我都不着急,只有你需要我的时候我才出现,这个模式就是懒汉式。

懒汉式:一开始比较懒,不去创建对象,等到程序需要我的时候,实在没法再拖了,就只能创建对象了

public class LazyInitializedSingleton {
    //需要对象时候再去创建
    private static LazyInitializedSingleton instance;
    //私有化构造器
    private LazyInitializedSingleton(){}
    /**对外暴露的获取单例对象的方法
      *存在多线程并发不安全问题,可以通过加锁synchronized关键字 锁会影响性能
    */
    public static synchronized LazyInitializedSingleton getSingletonInstance(){
        //判断是否已经创建了对象,没有就创建,有就直接返回
        if(instance == null){
            instance = new LazyInitializedSingleton();
        }
        return instance;
    }
}

加锁后,线程安全问题解决了,但是由于加锁又带来了性能的问题;真是一波未平一波又起啊,性能问题在也是极其重要的问题,这里我们就要换一个思路了

2. 静态内部类

用静态内部类的方式来实现单例模式

public class InnerHelperSingleton {

    private InnerHelperSingleton(){}

    //静态内部类,只在getInstance方法内使用
    private static class SingletonHelper{
        private static final InnerHelperSingleton INSTANCE = new InnerHelperSingleton();
    }
    //返回接口
    public static InnerHelperSingleton getSingletonInstance(){
        return SingletonHelper.INSTANCE;
    }
}

这种方式跟饿汉式方式采用的机制类似,但又有不同;两者都是采用了类加载的机制来保证初始化实例时只有一个线程。
饿汉式静态内部类方法的不同点:
饿汉式是只要Singleton类被加载就会实例化,没有懒加载
静态内部类方式结合了“饿汉”和“懒汉”二者的优点,是在需要实例化时,调用getInstance方法,才会加载SingletonHolder类,实例化Singleton。
由于类的静态属性只会在第一次加载类的时候初始化,所以在这里我们也保证了线程的安全性,所以通过这种静态内部类的方式解决了资源浪费和性能的问题。

静态资源内部类的方式是比较推荐的一种写法。