DesignPattern-创建型-Singleton

1、简介

  单例模式下,一个类只能有一个实例。外部能获取到的实例都是一样的。

  Spring中的Bean默认就是单例的。

  单例减少了内存占用。

  如何实现?

    唯一实例:static。

    外部不能再创建对象:将构造器声名为私有的。

    外部获取单例对象:声名一个工厂方法返回单例引用。

2、实现

/**
 * 线程不安全
 * 延迟初始化
 */
class Singleton1{
    private Singleton1(){}
    private static Singleton1 singleton1;
    public static Singleton1 getInstance(){
        if(singleton1==null)
            singleton1=new Singleton1();
        return singleton1;
    }
}

/**
 * Singleton1的改进
 * 用锁保证线程安全
 * 延迟初始化
 * 由于锁住了整个方法,效率较低
 */
class Singleton3{
    private Singleton3(){}
    private static Singleton3 singleton3;
    public static synchronized Singleton3 getInstance(){
        if(singleton3==null)
            singleton3=new Singleton3();
        return singleton3;
    }
}

/**
 * 利用了虚拟机类加载的机制,在类加载时就完成了实例创建
 * 安全发布,线程安全
 */
class Singleton2{
    private Singleton2(){}
    private static final Singleton2 singleton2=new Singleton2();
    public static Singleton2 getInstance(){
        return singleton2;
    }
}

/**
 * 相较于锁住整个方法,减小了同步代码块的大小
 * 并且,只有在进行实例创建时才进行同步
 * 同时,为了防止运行时的指令重排序,将singleton4声名为volatile
 * 安全发布,线程安全
 * 延迟初始化
 */
class Singleton4{
    private Singleton4(){}
    private static volatile Singleton4 singleton4;
    public static Singleton4 getInstance(){
        if(singleton4==null){
            synchronized (Singleton4.class){
                if (singleton4==null)
                    singleton4=new Singleton4();
            }
        }
        return singleton4;
    }
}

/**
 * 使用了静态内部类来持有单例
 * 在静态内部类加载时完成了实例创建,是安全的发布
 * 只用在访问静态内部类的静态域时,才会发生静态内部类的加载和单例的创建,因此是延迟初始化的
 */
class Singleton5{
    private Singleton5(){}
    private static class InnerHolder{
        private static Singleton5 singleton5=new Singleton5();
    }
    
    public static Singleton5 getInstance(){
        return InnerHolder.singleton5;
    }
}

 

posted @ 2021-09-17 12:40  Lqblalala  阅读(29)  评论(0)    收藏  举报