设计优化之单例模式

单例模式

定义: 对象创建模式,确保系统中一个类只产生一个实例

使用单例的好处:

1): 对频繁使用的对象,省略创建对象所花费的时间

2):new 操作次数的减少,对系统内存的使用频率也会降低,减轻GC压力,缩短GC停顿时间。

创建单例模式

第一种方式):类一加载就创建

public class Singleton {
    /**
    私有化构造方法,外界不能通过new运算符创建对象
     */
    private Singleton(){
        System.out.println("create singleton");
    }

    /**
     * 实例化Singleton对象,static修饰,在类加载时实例化
     */
    private static Singleton instance = new Singleton();

    /**
     * 提供一个接口,外界可以通过该接口获取Singleton对象
     */
    public static Singleton getInstance(){
        return instance;
    }
}

弊端:在使用单例类时,不管有没有使用单例对象,单例变量都会通过new运算符实例化。

public class Singleton {
    /**
    私有化构造方法,外界不能通过new运算符创建对象
     */
    private Singleton(){
        System.out.println("create singleton");
    }

    /**
     * 实例化Singleton对象,static修饰,在类加载时实例化
     */
    private static Singleton instance = new Singleton();

    /**
     * 提供一个接口,外界可以通过该接口获取Singleton对象
     */
    public static Singleton getInstance(){
        return instance;
    }

    public static void getString(){
        System.out.println("ceateString in Singleton");
    }
}

//执行Singleton.getString()程序输出
create singleton
ceateString in Singleton
//不管有没有使用单例对象,单例变量都会通过new运算符实例化

第二种方式):延迟加载

先将单例变量声明为null,只有使用单例对象时,才通过new运算符创建实例

public class LazySingleton {
    /**
    声明私有的构造器
     */
    private LazySingleton(){
        System.out.println("create lazySingleton");
    }

    /**
     * 单例变量初始化时不进行实例化
     */
    private static LazySingleton instance = null;

    /**
     * 1)提供获取单例对象的接口
     * 2)加锁:
     *   防止线程1在未赋值前,线程2可能判断instance == null,此时会产生两个单例对象
     * @return
     */
    public static synchronized LazySingleton getInstance(){
        if(instance == null){
            instance = new LazySingleton();
        }
        return instance;
    }
}

弊端:多线程调用时可能会产生两个单例对象,使用了sychonized可以预防该现象出现,但时耗远远大于第一种模式

第三种方式):使用私有的静态成员内部类的方式

public class StaticSingleton {
    /**
     * 将构造方法私有化
     */
    private StaticSingleton(){
        System.out.println("create staticSingleton");
    }

    /**
     * 创建静态成员内部类,在内部类中创建单例对象
     *  --:静态成员内部类在外部类加载时不会加载,只有在调用时才会加载
     */
    private static class SingletonHolder{
        private static StaticSingleton instance = new StaticSingleton();
    }

    /**
     * 提供获取单例的接口
     *  ---:满足了只有在使用单例时才使用new进行实例化,也不必使用synchonized关键字
     */
    public static StaticSingleton getInstance(){
        return SingletonHolder.instance;
    }

    public static void  get(){
        System.out.println("get");
    }
}

好处:解决了延迟加载的问题,单例可以在使用时创建,也不必使用synchonized关键字

金麟岂能忍一世平凡 飞上了青天 天下还依然
原文地址:https://www.cnblogs.com/Auge/p/11536615.html