设计模式:单例模式

序言

今天呢,来说一下设计模式吧,一个强大且高效的设计模式,可以大大提高代码的可读性,保证我们代码的可靠性也会提高程序的效率,毫无疑问使用设计模式来优化程序十分重要,但我们光会用可不行,一定要知其然知其所以然,这样才能学习到其中的核心思想,今天说一下设计模式中的单例模式吧!

单例模式

单例模式:顾名思义,使用单例模式会保证我们的类只有一个实例。

设计步骤

保证类只有一个实例

  • 构造函数私有化
  • 对外提供一个获取实例的方法

单机模式下的单例:懒汉式

class Singleton {
  
    private static volatile Singleton singleton=null;
    //私有化构造函数
    private Singleton(){
    }
    //懒汉式
    public static Singleton getSingleton(){
        if (singleton==null) {
                singleton = new Singleton();
        }
        return singleton;
    }
}

可以看出以上就是单机模式下的单例了

出现的问题

在并发访问情况下是有问题的,当singletonnull,当多个线程走到(singletonnull) 这里时,都会进入if代码块中进而会创建出多个实例

解决方法

可以采用双重检测机制来解决以上情况

懒汉式->优化

class Singleton {
    private static volatile Singleton singleton=null;
    private Singleton(){

    }
    //懒汉式
    public static Singleton getSingleton(){
        //双重检测机制:在并发场景下确保实例的唯一性
        if (singleton==null){
            synchronized (Singleton.class) {
                if (singleton==null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

第一个if判断作用:提高效率,当已经singleton!=null时直接返回实例即可

synchronized来保证多线程环境下同一时间只有一个线程执行以下代码块

第二个if判断作用:在锁被释放,新的线程争抢到锁后判断一下当前是否已经存在实例

懒汉式->终极优化

大家觉得现在这个类是单例的吗?

其实它还不是完全单例的,还可以通过反射,序列化,克隆的方式创建出新的实例!那么我们就针对这些问题再做进一步的优化。

class Singleton implements Serializable,Cloneable {
    static final long serialVersionUID=45L;
  
    private static volatile Singleton singleton=null;

    private static boolean isFristCreate = true;//默认是第一次创建(防止反射获取)

    private Singleton(){
        //防止反射破坏单例
        if (isFristCreate){
            //防止并发情况下多个反射同时获取
            synchronized (Singleton.class){
                if (isFristCreate) {
                    isFristCreate = false;
                }else {
                    throw new RuntimeException("阻止通过反射来获取多个实例");
                }
            }
        }else {
            throw new RuntimeException("阻止通过反射来获取多个实例");
        }

    }
    //懒汉式
    public static Singleton getSingleton(){
        //双重检测机制:在并发场景下确保实例的唯一性
        if (singleton==null){
            synchronized (Singleton.class) {
                if (singleton==null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    //防止序列化破坏单例,序列化时会直接调用该方法,保证单例
    Object readResolve() throws ObjectStreamException {
        return singleton;
    }

    //防止克隆破坏单例
    protected Singleton clone() throws CloneNotSupportedException {
        return singleton;
    }
}

以上就是单例模式——懒汉式的完全体了!

枚举形式

enum Singleton{
    GO()
}

枚举天生就可以保证单例,且枚举方式可以防止反射,克隆,序列化破坏单例。

饿汉式

class Singleton {
  
    private static volatile Singleton singleton=new Singleton();
    //私有化构造函数
    private Singleton(){
    }
    //懒汉式
    public static Singleton getSingleton(){
        return singleton;
    }
}

这种方式在类加载阶段就会创建出实例

静态内部类

class StaticSingleton implements Serializable {
    private static class InnerSingleton{
        private static final StaticSingleton staticSingleton=new StaticSingleton();
    }
    private StaticSingleton(){
    }
    public static StaticSingleton get(){
        return InnerSingleton.staticSingleton;
    }
}

在保证了单例的前提下,只有调用内部类的属性时才会初始化,节省了空间

总结

以上就是创建单例模式的几种方法了,大家掌握了几种呢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guojunjiang12345

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值