[设计模式] ------ 单例模式

本文深入探讨单例模式的五种实现方式,包括饿汉式、懒汉式、双重检查锁、静态内部类及枚举方法,分析每种方法的优缺点,如线程安全性、延迟加载等。

单例模式,是众多设计模式中,写法最多,套路最多,坑最多,面试被问最多的设计模式。
基本上,单例模式在面试中已经被问烂了,依稀记得我的上家公司面试我的时候,说到设计模式,直接就说,写一种设计模式,但单例除外。
但不得不说,单例由于其概念简单,实用性广的特点,在项目中很是常见。

概念:

单例模式就是确保一个类只有一个实例的设计模式。
设计的思路无非就是先new一个实例,以后都用这个实例就行了。
难点在于什么时机new出这个实例,以及如何确保有且只有这一个实例。

五种常见的单例实现

第一种:饿汉式(新手写法)

提前加载,所以也无法延迟加载,效率不高,不推荐

public class HungurySingleton { //缺点,无法延时加载,没有使用就已经加载了
    private static final HungurySingleton mInstance = new HungurySingleton();
    private HungurySingleton(){
    }
    public static HungurySingleton getHunguryInstance(){
        return mInstance;
    }
}

第二种:懒汉式(入门写法)

没有提前加载,但多线程下并发可能会出现多个实例

public class LazySingleton {
    private static LazySingleton mInstance;
    private LazySingleton(){
    }
    public static LazySingleton getmInstance(){
        if(mInstance == null){//就是这里,如果两个线程并发访问,里面的new语句就会执行两次
            mInstance = new LazySingleton();
        }
        return mInstance;
    }
}

第三种:双重检查锁(能写出这个,就有点东西了)

很明显,这样写,就不怕上面的那种并发问题了

public class DLCSingleton {
    private static volatile DLCSingleton mInstance =null; //volatile关键字是为了禁止编译器对 volatile关键字修饰的变量进行重排序,并保证volatile变量的读操作发生在写操作之后
    private DLCSingleton(){
    }
    public static DLCSingleton getmInstance(){
        if(mInstance == null){ //第一次检查
            synchronized (DLCSingleton.class){ //同步代码块
                if(mInstance == null){ //第二次检查
                    mInstance = new DLCSingleton();
                }
            }
        }
        return mInstance;
    }
}

第四种:静态内部类实现(高手写法)

利用静态内部类是在被调用时才会被加载,算是延迟加载
static final 修饰instance,初始化后就不会被修改,保证线程安全

public class StaticInnerSingleton { //完成了懒汉式的延迟加载,同时static保证了线程安全。
    private  StaticInnerSingleton(){
    }
    public static StaticInnerSingleton getIntance(){
        return SingletonHolder.mIntance;
    }
    private static class SingletonHolder{ //私有的,初始化的时候,没有调用getIntance方法则不会加载
	//static,final是jvm提供的同步机制,初始化后就无法修改了
        private static final StaticInnerSingleton mIntance = new StaticInnerSingleton();  
    }
}

第五种:(牛人写法)

枚举做单例,think in java中的神思想,虽然我从来没见过谁在项目中实战用到
但看这个网上说的热火朝天,也是各种好处,比如写法简单,线程安全

public enum EnumSingleton {
    SPRING,SUMMER,AUTUMN,WINTER;
}

总结:

我只是列出常用的,当然,还有其他版本
比如静态代码块的写法,
还有双重检查锁前一个版本,就是没有第一步判空的写法,
还有用synchronized修饰方法的写法等等。

是我的话,一般情况下,
确保项目肯定没有并发的话,懒汉写法就没问题了。
一考虑到并发,就用双重检查锁的写法,是常用而且稳定的。
至于枚举写法,总之我还没有习惯这么写,可以尝试用用。

以上是个人意见,欢迎评论指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值