龙空技术网

Java编程中单例模式的7种实现方法

我喜欢思考 68

前言:

而今大家对“java中的单例模式的使用场景有哪些”大概比较注重,小伙伴们都想要剖析一些“java中的单例模式的使用场景有哪些”的相关文章。那么小编同时在网络上搜集了一些关于“java中的单例模式的使用场景有哪些””的相关文章,希望小伙伴们能喜欢,大家快快来了解一下吧!

引言

在 Java 编程中,对象的创建和实例化是通过使用 new 关键字以及调用类中定义的构造函数来完成的。下面是一个简单的示例:

Clazz instance = new Clazz();

我们可以阅读如下代码片段:

在这个例子中,new Clazz() 调用了 Clazz 类的构造函数,创建了一个新的对象实例,并将这个新对象的引用赋值给变量 instance。

当我们需要创建一个单例(Singleton)模式的类时,我们的目标是确保整个应用程序中只有一个类的实例存在。为了实现这一点,我们需要遵循一些关键的步骤和约定:

私有化构造函数:所有构造函数都应该是私有的,这样可以防止外部通过 new 关键字创建类的实例。持有单例对象的变量:类内部需要一个私有的静态变量来保存单例对象。这个变量通常是私有的、静态的,并且可以是最终的(final),以确保其值不会被改变。单例对象的命名:这个变量通常被命名为 instance 或者 INSTANCE,以表明它代表了类的唯一实例。提供全局访问点:需要提供一个公开的静态方法,允许其他对象访问这个单例实例。这个方法通常被称为 getInstance(),并且它负责控制类的实例化过程。静态工厂方法:getInstance() 方法也被称为静态工厂方法,因为它不直接返回一个新创建的对象,而是通过某种逻辑来提供对单例对象的引用。

有了这些理解,让我们更深入地理解 singleton 。以下是为类创建单例对象的7种方法。

方法1:懒汉式(线程不安全)

这是最基本的实现方式,只在getInstance()方法第一次被调用时才创建实例。

private static Clazz instance;public static Clazz getInstance() {    if (instance == null) {        instance = new Clazz();    }    return instance;}
方法2:懒汉式(线程安全)

与第一种方法类似,但是通过使用 synchronized 关键字来确保线程安全。

private static volatile Clazz instance;public static synchronized Clazz getInstance() {    if (instance == null) {        instance = new Clazz();    }    return instance;}
方法3:饿汉式(线程安全)

在类加载时就创建单例对象,这种方式简单且线程安全。

private static final Clazz instance = new Clazz();public static Clazz getInstance() {    return instance;}
方法4:双重检查锁定(Double-Checked Locking)

这种方法结合了懒汉式和饿汉式的优点,同时使用了volatile关键字和synchronized块来保证线程安全。

private static volatile Clazz instance;public static Clazz getInstance() {    if (instance == null) {        synchronized (Clazz.class) {            if (instance == null) {                instance = new Clazz();            }        }    }    return instance;}
方法5:静态内部类

通过Java的类加载机制来实现单例,这种方式是线程安全的,并且防止了通过反射和序列化的方式破坏单例。

private static volatile Clazz instance;public static Clazz getInstance() {    if (instance == null) {        synchronized (Clazz.class) {            if (instance == null) {                instance = new Clazz();            }        }    }    return instance;}
方法6:枚举单例

使用Java枚举类型的特性来实现单例,这是最简单且最安全的方式。

public enum Clazz {    INSTANCE;    public void doSomething() {        // ...    }}
方法7:利用 Spring 框架或 Guava 库

这种方法相对繁琐,但如果你原本就基于 Spring 框架在开发项目,又或者你的项目中之前就依赖引入了 Guava 库,那采用这种方法也很合适。

基于 Guava 库

import com.google.common.base.Supplier;import com.google.common.base.Suppliers;public class SupplierSingleton {    private SupplierSingleton() {}    private static final Supplier<SupplierSingleton> singletonSupplier = Suppliers.memoize(()-> new SupplierSingleton());    public static SupplierSingleton getInstance() {        return singletonSupplier.get();    }    public static void main(String[] args) {        SupplierSingleton supplierSingleton = SupplierSingleton.getInstance();    }}
基于 Spring 框架

这种方法在基于 Spring Boot 框架的企业开发中被大量使用。

import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Scope;class SingletonBean { }@Configurationpublic class SingletonBeanConfig {    @Bean    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)    public SingletonBean singletonBean() {        return new SingletonBean();    }    public static void main(String[] args) {        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SingletonBean.class);        SingletonBean singletonBean = applicationContext.getBean(SingletonBean.class);    }}

Spring是一个非常流行的框架,上下文和依赖注入是Spring的核心。

import com.google.inject.AbstractModule;import com.google.inject.Guice;import com.google.inject.Injector;interface ISingletonBean {}class SingletonBean implements  ISingletonBean { }public class SingletonBeanConfig extends AbstractModule {    @Override    protected void configure() {        bind(ISingletonBean.class).to(SingletonBean.class);    }    public static void main(String[] args) {        Injector injector = Guice.createInjector(new SingletonBeanConfig());        SingletonBean singletonBean = injector.getInstance(SingletonBean.class);    }}
结论

在软件开发过程中,我们经常会遇到各种业务问题和非功能性需求的挑战,例如性能优化、系统安全性、以及对CPU和内存资源的限制等。在这些约束条件下,设计模式应运而生,为我们提供了一套成熟的解决方案,帮助我们有效地解决问题和优化系统设计。

Singleton模式正是这样一种设计模式,它确保了一个类在应用程序中只有一个实例存在,并且提供了一个全局访问点。这种模式在需要全局或上下文范围内可访问的对象时显得尤为重要,例如在创建动态异构容器、管理上下文环境、实现对象池、或者设计具有战略意义的功能对象时。

在Java编程领域,Singleton模式的应用非常广泛。它不仅有助于减少资源消耗和避免不必要的对象创建,还可以保证应用程序中某些关键对象的唯一性,从而确保数据的一致性和系统的稳定性。通过使用Singleton模式,我们可以确保在任何给定时间点,对于共享资源的访问都是同步的,避免了多线程环境下的并发问题。

总的来说,Singleton模式是一种简单而强大的设计模式,它通过限制实例化来解决特定的设计问题。在面对复杂的业务逻辑和非功能性需求时,合理运用Singleton模式可以提高代码的可维护性、可扩展性和性能。因此,对于Java开发者来说,深入理解和掌握这种模式是非常有价值的。

标签: #java中的单例模式的使用场景有哪些