设计模式我之见

单例模式

java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍五种:饿汉式单例、懒汉式单例、双重锁检查式单例、静态内部类单例、枚举单例。
无论如何使用哪种写法,其最根本的目的在于创造一个类的单一实例,其次是性能与代码的简洁,所以饿汉式与枚举单例是我个人认为最好用的写法。

饿汉式

public class Singleton {
    private Singleton() {}
    private static final Singleton singleton = new Singleton();
    public static Singleton getInstance() {
        return singleton;
    }
}

因其在类初始化的时候就生成实例,所以称其为饿汉式,且jvm保证了其线程安全。有的文章占认为这种写法用资源;如果后期这个单例没有被使用,会造成资源浪费,我认为这点缺点与其优点相比不值一提。

懒汉式

public class Singleton {
    private Singleton() {}
    private static Singleton singleton = null;
    public static Singleton getInstance() {
         if (singleton== null) {  
             singleton= new Singleton();
         }  
        return singleton;
    }
}

懒汉式顾名思义,在出现调用getInstance方法的时候才会实例化对象,所以他的优缺点正好与饿汉式相反,线程不安全但不会造成资源浪费。也正如我上文所说,我认为单例模式的根本目的创造一个类的单一实例,所以线程不安全是不能接受的,不推荐使用懒汉式单例。

双重锁检查式

public class Singleton {
    private Singleton() {}
    private static Singleton singleton = null;
    
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton3();
                }
            }
        }
        return singleton;
    }
}

双重锁的特点是线程安全,且确保了只有第一次调用单例时才会做同步,且避免了锁加在整个方法上导致的每次都同步的性能损耗,但仍降低了程序响应速度和性能。

静态内部类式

public class Singleton {
    private Singleton() {}
    private static class LazyHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static final Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

静态内部类利用了jvm类加载机制保证了线程安全,且外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE ,所以静态内部类既节省了内存开销又保证了线程安全,但它的一个致命弱点是无法传参。

枚举单例

public enum Singleton {
    INSTANCE;

    public void getInstance() {
    }
}

枚举类是jdk1.5引入的,它最大的特点是没有构造方法。前面的四种单例模式写法,即使都将构造器私有化,但这在反射攻击和反序列化面前都不起作用,仍通过获取构造器来创建多个实例,而枚举类则不存在这个问题,且枚举类本身为单例模式,所以单元素的枚举类型已经成为实现Singleton的最佳方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>