单例模式详解

一、前言

单例模式是一种常用的软件设计模式,在它的核心结构中值包含一个被称为单例的特殊类,一个类只有一个实例,即一个类只有一个对象实例。该模式在Java和Android代码开发中很是常见,在面试过程中经常会被问到,我曾以该问题面试很多工作5年以上的同学,他们很难将问题答全,甚至连最基本的懒汉模式和恶汉模式也没能说出来,为此有必要总结一下。

二、单例模式

单例模式中分为懒汉模式和饿汉模式,关于这两种模式很多同学可能一时半会记得,但是时间长了就区分不清楚了,关于这两个名词可以这样理解。懒汉模式可比方成一个汉子,他比较懒,你不去叫唤他让他干啥,他是不会动弹的,放在单例模式的代码中就可以对应的这样理解了,如果不去使唤一个对象来完成某项功能,该对象也同样是懒得实例化的。

2.1 懒汉模式

以下便是最简单的懒汉模式,是非线程安全的,一般在代码中不会。

public class SingletonDemo {
    private static SingletonDemo instance;
    private SingletonDemo(){}
    public static SingletonDemo getInstance(){
        if (instance == null) {
            instance = new SingletonDemo();
        }
        return instance;
    }
}

为了保证懒汉模式单例的线程安全,常见的用法便是加锁,但是加锁的同时又要考虑到程序运行的效率,常用的懒汉模式的单例是加上双锁,代码如下:

public class SingletonDemo {
    private volatile static SingletonDemo singletonDemo;
    private SingletonDemo(){}
    public static SingletonDemo getInstance(){
        if (singletonDemo == null) {
            synchronized (SingletonDemo.class) {
                if (singletonDemo == null) {
                    singletonDemo = new SingletonDemo();
                }
        }
        return singletonDemo;
    }
}

这种懒汉模式便是常用的单例模式,针对这种双锁需要在JDK1.5之后才能达到双锁的效果,目前使用的JDK多是在JDK1.5版本以上。

2.2 饿汉模式

针对单例模式中饿汉模式,可以这般理解,饿汉好比一个饥饿的人,所以他会最大程度的消耗资源来满足的饥饿而不管他是否需要。放在单例模式的饿汉模式的代码实现中,饿汉模式会在代码的运行初期就将单例给实例化。

//第一种写法
public class SingletonDemo {
    private static SingletonDemo instance = new SingletonDemo();
    private SingletonDemo(){}
    public static SingletonDemo getInstance(){
        return instance;
    }
}
//第二种写法
public class SingletonDemo {
    private static SingletonDemo instance = null;
    static{
        instance = new SingletonDemo();
    }
    private SingletonDemo(){}
    public static SingletonDemo getInstance(){
        return instance;
    }
}

以上两种单例模式都会在设计模式中有讲解到,用法也各有优劣,懒汉模式的优点便是在代码中没有单例的情况下,不会去加载单例类的资源不会造成资源的浪费。缺点也很明显,加锁同步会带来程序运行效率的损失。饿汉模式的优缺点恰好与懒汉模式相反,如果明确知道单例对象在程序代码中用的很频繁,就可以考虑使用饿汉模式了。
在除去懒汉模式和饿汉模式,《effective java》为我们提供了另外两种单例模式的实现方式,一种是通过静态内部类来实现,另一种便是通过枚举来实现。
内部类单例模式

private StaticInnerSingleton() {
        if (SingletonHolder.instance != null) {
            throw new IllegalStateException();//此处是避免单例被反射调用
        }
    }

    private static class SingletonHolder {
        private static StaticInnerSingleton instance = new StaticInnerSingleton();
    }

    public static StaticInnerSingleton getInstance() {
        return SingletonHolder.instance;
    }

}

静态内部类兼顾了懒汉模式和恶汉模式的优点,但是又避免了它们缺点,是《effective java》比较推崇的一种单例模式的实现。
枚举单例模式

public enum SingletonDemo6 {
    instance;
    public void whateverMethod(){
    }
}

《effetive java》的作者同样很推崇这种实现方式,这种方式线程安全,且不能够被反射,但是奈何这种方法用的还是比较少,不是很常见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值