Java设计模式(1)单例模式

2024-04-18 13:24:38 浏览数 (2)

前言

在软件开发的世界里,设计模式如同一本精妙的编码诗集,已经成为一种标准的编程实践。在Java编程中,设计模式很重要。是软件开发中广泛应用的一种编程方法,它可以帮助开发人员更快地编写出高效、可靠和可维护的代码。 本人将制作一个关于Java设计模式的系列文章,总共23种设计模式将以一篇一篇文章讲解,代码笔记已开源:Gitee点击跳转 。本文是这个系列的第一篇章,我们将讲解一下单例模式的实现方式、应用场景以及它的用途。

单例模式

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点供外部代码获取该实例。这种模式的主要目的是限制某个类的实例化过程只能发生一次,避免多次创建相同对象,确保在整个应用程序中只存在一个唯一实例。

应用场景

  1. 资源管理器: 例如,数据库连接池、线程池等资源的管理,确保全局只有一个资源池。
  2. 配置管理器: 在系统中负责读取配置信息,保持全局唯一性,避免多次读取配置文件。
  3. 日志记录器: 用于记录系统日志,保持唯一的记录器实例,确保日志信息一致性。

代码实现

懒汉式

这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。

代码语言:javascript复制
public class Singleton {
    private static Singleton instance;
    public Singleton() {}
    public static Singleton getInstance(){
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

要想懒汉式单例能够在多线程中很好的工作,得对getInstance方法加锁synchronized,但是效率很低。

饿汉式

这种方式是线程安全的方式,因为它是基于 classloader 机制避免了多线程的同步问题。就是有点浪费资源,因为在类加载的时候就初始化了。

代码语言:javascript复制
public class Singleton {
    private static final Singleton instance = new Singleton();
    public Singleton() {}
    public static Singleton getInstance(){
        return instance;
    }
}

静态内部类

这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程。因为SingletonHolder是一个静态内部类,它包含一个静态的INSTANCE成员变量,用于存储单例对象。在第一次调用getInstance方法时,静态内部类会被加载,从而创建单例对象。这种方式既达到了线程安全又兼顾了延迟加载的需求。

代码语言:javascript复制
public class Singleton {
    public Singleton() {}
    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
    private static class SingletonHolder{
        public static final Singleton INSTANCE = new Singleton();
    }
}

双重校验锁

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

代码语言:javascript复制
public class Singleton {
    private static volatile Singleton instance;
    public Singleton() {}
    public static Singleton getInstance(){
        if (instance == null){
            synchronized (Singleton.class){
                if (instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

枚举方式

这种方式用的比较少,但这是实现单例模式的最佳方法,它更简洁,自动支持序列化机制,绝对防止多次实例化。

代码语言:javascript复制
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

结尾

一般情况下,不建议使用懒汉式,建议使用饿汉式。只有在要明确实现 lazy loading 效果时,才会使用静态内部类方式。如果涉及到反序列化创建对象时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用双重校验锁方式。选择哪种实现方式需要根据具体需求来决定,需要综合考虑线程安全、性能、代码复杂度、延迟加载等因素。

0 人点赞