Java设计模式之单例模式

简介: 在软件工程中,单例模式是一种常用的设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。Java作为一门广泛使用的编程语言,实现单例模式是面试和实际开发中的常见需求。

在软件工程中,单例模式是一种常用的设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。Java作为一门广泛使用的编程语言,实现单例模式是面试和实际开发中的常见需求。本文将深入探讨Java中的单例模式,包括其优缺点分析、实现方式等。

singleton.jpg

优缺点分析

优点

  • 内存利用率高:因为只创建一个实例,减少了内存的开销。
  • 性能提高:避免了频繁的创建和销毁对象所带来的性能开销。
  • 共享资源:可以方便地共享数据。

缺点

  • 不支持有参数的构造函数:单例模式通常不能接受参数,这限制了其使用场景。
  • 扩展困难:由于单例模式的特殊性,扩展时需要修改代码,违背了“开闭原则”。
  • 隐藏类之间的依赖关系:由于直接使用了单例类,使得类之间的依赖关系不明显。

单例模式的实现

单例模式的实现比较简单,每次获取实例之前先判断其是否存在,不存在则创建,存在则直接返回。单例模式的实例只能由其自身去创建和销毁,不允许其它类通过new关键字去创建。单例模式常见的写法由饿汉式、懒汉式(线程安全)、双重检查锁、静态内部类。以下是这些写法的具体实现。

饿汉式

饿汉式是指在类加载时就完成了实例的初始化,本质上是利用类加载机制保证实例的唯一性和线程安全。

package cn.xj.xjdoc.singleton;

/**
 * 单例模式--饿汉式
 */
public class HungrySingleton {
   
   
    private static final HungrySingleton INSTANCE = new HungrySingleton();

    /**
     * 构造方法私有化
     * 保证外部无法直接通过new关键字来创建此类的实例
     */
    private HungrySingleton(){
   
   

    }

    /**
     *获取实例的public的静态方法
     */
    public static HungrySingleton getInstance(){
   
   
        return INSTANCE;
    }
}

懒汉式

懒汉式指全局的单例实例在第一次被使用时构建。为了解决线程安全问题,增加synchronized关键字,使得在同一时刻,只有一个线程能够访问这个方法。

package cn.xj.xjdoc.singleton;

/**
 * 单例模式--懒汉式
 */
public class LazySingleton {
   
   

    private static LazySingleton instance;

    /**
     * 构造方法私有化
     * 保证外部无法直接通过new关键字来创建此类的实例
     */
    private LazySingleton(){
   
   

    }

    /**
     *获取实例的public的静态方法,
     *使用synchronized锁,保证在同一时刻,只有一个线程能执行该方法,避免了多线程下创建多个实例的问题。
     */
    public static synchronized LazySingleton getInstance(){
   
   
        //实例为null则创建实例
        if(instance == null){
   
   
            instance = new LazySingleton();
        }

        return instance;
    }

}

双重检查锁

双重检查锁定在懒汉式的基础上做了进一步的优化,既保证了懒加载,又保证了线程安全,同时减少了锁的粒度,提高了性能。

package cn.xj.xjdoc.singleton;

/**
 * 单例模式--双重检查锁
 */
public class DoubleCheckedLockSingleton {
   
   

    // 声明一个私有的静态变量instance,并使用volatile关键字修饰。
    // volatile确保instance变量的可见性和禁止指令重排序,对于双重检查锁定模式非常关键。
    private volatile static DoubleCheckedLockSingleton instance;

    /**
     * 构造方法私有化
     * 保证外部无法直接通过new关键字来创建此类的实例
     */
    private DoubleCheckedLockSingleton(){
   
   

    }

    /**
     *获取实例的public的静态方法
     */
    public static DoubleCheckedLockSingleton getInstance(){
   
   
        // 第一次检查:如果instance不为null,则不需要进入同步块,直接返回实例。
        // 这样做的好处是,只有第一次调用时才会进行同步,之后的调用由于instance已经被实例化,直接返回,提高了效率。
        if(instance == null){
   
   
            // 使用synchronized锁,,确保多线程环境下的线程安全
            synchronized (DoubleCheckedLockSingleton.class){
   
   
                //实例为null则创建实例
                if(instance == null){
   
   
                    instance = new DoubleCheckedLockSingleton();
                }
            }
        }
        return instance;
    }

}

静态内部类

静态内部类单例模式的实现思路是:利用JVM在加载外部类的过程中不会加载静态内部类,只有在内部类被使用时才会被加载。这样不仅能延迟内部类的加载时间,还能保证线程安全。

package cn.xj.xjdoc.singleton;


/**
 * 单例模式--静态内部类
 */
public class StaticNestedClassSingleton {
   
   
    /**
     * 构造方法私有化
     * 保证外部无法直接通过new关键字来创建此类的实例
     */
    private StaticNestedClassSingleton(){
   
   

    }

    // 静态内部类
    private static class SingletonHolder {
   
   
        // 在内部类中持有外部类的实例,并且可以被直接初始化
        private static final StaticNestedClassSingleton INSTANCE = new StaticNestedClassSingleton();
    }
    /**
     *获取实例的public的静态方法
     */
    public static StaticNestedClassSingleton getInstance(){
   
   
        return SingletonHolder.INSTANCE;
    }
}

总结

单例模式是一种简单但非常实用的设计模式,在Java开发中有广泛的应用。选择合适的实现方式,可以在保证性能的同时,确保程序运行的正确性。然而,任何设计模式都不是万能的,使用单例模式时也应该考虑其适用场景和潜在的缺点。

目录
相关文章
|
22小时前
|
设计模式 消息中间件 Java
Java 设计模式:探索发布-订阅模式的原理与应用
【4月更文挑战第27天】发布-订阅模式是一种消息传递范式,被广泛用于构建松散耦合的系统。在 Java 中,这种模式允许多个对象监听和响应感兴趣的事件。
8 2
|
22小时前
|
设计模式 算法 Java
Java 设计模式:探索策略模式的概念和实战应用
【4月更文挑战第27天】策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在 Java 中,策略模式通过定义一系列的算法,并将每一个算法封装起来,并使它们可以互换,这样算法的变化不会影响到使用算法的客户。
6 1
|
1天前
|
设计模式 安全 Java
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
|
4天前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
4天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
|
4天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
4天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
|
4天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
10天前
|
设计模式 算法 Java
Java中的设计模式及其应用
【4月更文挑战第18天】本文介绍了Java设计模式的重要性及分类,包括创建型、结构型和行为型模式。创建型模式如单例、工厂方法用于对象创建;结构型模式如适配器、组合关注对象组合;行为型模式如策略、观察者关注对象交互。文中还举例说明了单例模式在配置管理器中的应用,工厂方法在图形编辑器中的使用,以及策略模式在电商折扣计算中的实践。设计模式能提升代码可读性、可维护性和可扩展性,是Java开发者的必备知识。
|
13天前
|
设计模式 算法 Java
小谈设计模式(30)—Java设计模式总结
小谈设计模式(30)—Java设计模式总结