设计模式之-单列设计模式,5种单例设计模式使用场景以及它们的优缺点

2023-12-22 10:51:52


前言

谈到单例设计模式时,以下是几种常见的实现方式。以及它们的优缺点

一、单列模式有哪几种实现?以及它们的优缺点?

懒汉式(Lazy Initialization):

优点:实现简单,只有在需要时才会创建实例。
缺点:在多线程环境下,存在线程安全问题。需要使用 synchronized 关键字保证线程安全,但会带来性能上的开销。

饿汉式(Eager Initialization):

优点:实现简单,线程安全,不存在多线程竞争的问题。
缺点:在程序启动时就创建实例,无论是否需要,可能会带来一定的资源浪费。

双重检查锁定(Double-Checked Locking):

优点:实现了懒加载和线程安全,同时避免了每次都需要获取锁的性能开销。
缺点:需要使用 volatile 关键字确保多线程环境下的可见性,实现稍微复杂。

静态内部类(Static Inner Class):

优点:实现了懒加载和线程安全,同时具有较高的性能和可读性。利用类加载机制保证了线程安全性。
缺点:无法在实例化时传递参数,适用于无需传参的场景。

枚举实现

优点:
线程安全:枚举实例在多线程环境下也是唯一的,不需要担心线程安全问题。
简洁明了:使用枚举实现单例非常简单,代码量少。
缺点:
无法延迟加载:枚举实例在类加载时就被实例化,无法实现延迟加载的特性。
无法传递参数:枚举实例无法在实例化时传递参数,适用于无需传参的场景。
使用场景:因此,使用枚举实现单例模式适合于简单的单例对象,且希望获得简洁的线程安全代码的情况。如果需要延迟加载或传递参数,其他实现方式可能更合适。

二、示列代码

懒汉式(Lazy Initialization)

public class LazySingleton {
    private static LazySingleton instance;
    
    private LazySingleton() {
        // 私有构造函数
    }
    
    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

饿汉式(Eager Initialization)

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();
    
    private EagerSingleton() {
        // 私有构造函数
    }
    
    public static EagerSingleton getInstance() {
        return instance;
    }
}

双重检查锁定(Double-Checked Locking)

public class DoubleCheckedSingleton {
    private static volatile DoubleCheckedSingleton instance;
    
    private DoubleCheckedSingleton() {
        // 私有构造函数
    }
    
    public static DoubleCheckedSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckedSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedSingleton();
                }
            }
        }
        return instance;
    }
}

静态内部类(Static Inner Class)

public class StaticInnerSingleton {
    private StaticInnerSingleton() {
        // 私有构造函数
    }
    
    private static class SingletonHolder {
        private static final StaticInnerSingleton instance = new StaticInnerSingleton();
    }
    
    public static StaticInnerSingleton getInstance() {
        return SingletonHolder.instance;
    }
}

枚举实现

public enum EnumSingleton {
    INSTANCE;
    
    // 可以在枚举中添加其他成员变量和方法
    
    public void doSomething() {
        // 单例的操作逻辑
    }
}

三、适用场景

不同的单例实现方式适用于不同的场景。以下是对上述几种单例实现方式适用场景的简要总结:

懒汉式(Lazy Initialization):

适用场景:在需要延迟加载单例实例的情况下,且对线程安全性要求不是特别高的场景。单线程环境或者有额外的同步措施保证线程安全时可以考虑使用。

饿汉式(Eager Initialization):

适用场景:在程序启动时就需要创建单例实例,并且对线程安全性要求较高的场景。适合于单例对象较小且占用资源较少的情况。

双重检查锁定(Double-Checked Locking):

适用场景:在需要延迟加载单例实例的情况下,对线程安全性要求较高,并且希望在多线程环境下获取单例实例时具有较好的性能。适合于单例对象较大或者创建过程较为复杂的情况。

静态内部类(Static Inner Class):

适用场景:在需要延迟加载单例实例的情况下,对线程安全性要求较高,并且希望使用简洁、清晰的代码实现。适合于单例对象较小且占用资源较少的情况。

枚举实现:

适用场景:在需要简洁、线程安全的单例实现,并且不需要延迟加载和传递参数的情况下。适合于单例对象较小且占用资源较少的情况。

总结

需要根据具体的需求和场景来选择适合的单例实现方式。考虑到线程安全性、延迟加载、性能以及代码的简洁程度等因素,选择最合适的单例实现方式对于保证应用的正确性和性能是很重要的。

文章来源:https://blog.csdn.net/qq_42262444/article/details/135145909
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。