设计模式之——单例模式

一、介绍

什么是单例模式?单例模式就是采取一定的方法保证在整个系统中,只能存在一个对象实例。该类提供一个静态方法返回对象实例。

为什么要采用单例模式?

  1. 资源共享: 当你需要多个对象共享某些资源(如数据库连接池、线程池、缓存等)时,可以使用单例模式确保所有对象都使用同一个实例,避免资源的浪费和冲突。

  2. 全局访问点: 在某些情况下,需要全局访问一个对象,例如日志记录器、配置管理器等,这时可以使用单例模式确保在整个应用程序中只有一个实例,并且可以在任何地方方便地访问它。

  3. 控制实例数量: 单例模式可以限制类的实例化次数,确保只有一个实例存在。这在某些情况下是必要的,例如线程池中只需要有固定数量的线程实例。

  4. 懒加载: 在需要时才创建对象实例,延迟实例化。这可以节省资源,提高性能,尤其是当对象的初始化开销较大时。

  5. 保持一致性: 有些对象在系统中只应该有一个实例存在,例如系统配置信息或应用程序状态等。使用单例模式可以确保这些对象始终保持一致性。

采用单例模式的好处是什么?

  • 节省资源: 单例模式可以节省系统资源,因为它限制了对象实例的数量。
  • 简化访问: 全局访问点使得对象可以在任何地方轻松访问,提高了代码的可维护性和可读性。
  • 确保一致性: 单例模式可以确保某些对象始终保持一致性,避免了状态的不一致性。

二、饿汉式单例

1、静态常量饿汉式

public class Singleton {
    // 静态常量,类加载时即创建
    private static final Singleton instance = new Singleton();
    
    // 私有构造函数,防止外部类实例化
    private Singleton() {}
    
    // 获取单例实例的静态方法
    public static Singleton getInstance() {
        return instance;
    }
    
}

优点:写法简单,在类装载的时候完成了实例化,避免了线程安全的问题。

缺点:没有达到 懒加载的效果。如果系统中没有使用到这个实例,就会造成内存浪费。

2、静态代码块饿汉式

public class Singleton {

    private static Singleton instance;
    
    static{
        instance = new Singleton();
    }

    // 私有构造函数,防止外部类实例化
    private Singleton() {}
    
    // 获取单例实例的静态方法
    public static Singleton getInstance() {
        return instance;
    }
    
}

优缺点同上,只是改变了代码方式。

三、懒汉式单例

1、线程不安全的懒汉式

public class Singleton {
    // 私有静态变量,初始值为 null
    private static Singleton instance;
    
    // 私有构造函数,防止外部类实例化
    private Singleton() {}
    
    // 获取单例实例的静态方法
    public static Singleton getInstance() {
        // 判断实例是否已经创建,如果未创建,则创建新实例
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
}

优点:起到了懒加载的作用

缺点:只能在单线程下去使用,在多线程环境下,可能存在两个线程同时进去了if语句造成创建多个实例。在开发过程中,禁止使用这种方式。

2、线程安全的懒汉式

public class Singleton {
    // 私有静态变量,初始值为 null
    private static Singleton instance;
    
    // 私有构造函数,防止外部类实例化
    private Singleton() {}
    
    // 获取单例实例的静态方法,使用synchronized关键字保证只有一个线程执行方法。
    public static synchronized Singleton getInstance() {
        // 判断实例是否已经创建,如果未创建,则创建新实例
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
}

优点:解决了线程不安全问题

缺点:效率低下,每个线程在执行getInstance()方法时都需要等待其他线程释放锁,但在正常情况中,只需要有一个线程创建一次实例,其他线程直接获取返回值就可以了,因此在实际开发中仍然不推荐使用。

3、双重检查的懒汉式(推荐使用)

使用了volatile关键字,这个关键字修饰的变量对所有线程可见。关于该关键字的详细解释请看:多线程-并发编程、面试难点(线程合集)-CSDN博客

public class Singleton {
    // 私有静态变量,初始值为 null
    private static volatile Singleton instance;
    
    // 私有构造函数,防止外部类实例化
    private Singleton() {}
    
    // 获取单例实例的静态方法
    public static Singleton getInstance() {
        // 双重判定解决线程安全问题,既保证了可以多线程访问,又保证了线程安全的问题。
        if (instance == null) {
            synchronized(singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    
}

优点:线程安全;懒加载;效率高;

缺点:无缺点,已经拉满了,开发中推荐使用!

4、静态内部类实现懒汉式(推荐使用)

这个实现原理是根据Java中类加载的顺序,在Singleton类加载时并不会加载静态内部类,而是只有在第一次调用的时候才会加载,借助这个类加载机制我们可以实现懒加载的单例。

public class Singleton {
    
    // 私有构造函数,防止外部类实例化
    private Singleton() {}

    //使用静态内部类完成懒汉式单例
    private static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    }
    
    // 获取单例实例的静态方法
    public static Singleton getInstance() {
        
        return SingletonInstance.INSTANCE;
    }
    
}

5、枚举实行单例模式(推荐使用)

public enum Singleton {
    INSTANCE;

    // 枚举方法
    public void doSomething() {
        System.out.println("Singleton instance is doing something.");
    }

}

  1. 线程安全: 枚举类型在 Java 中是线程安全的,因此不需要额外的同步措施来保证线程安全性。

  2. 简洁明了: 使用枚举实现单例模式代码简洁清晰,不需要手动编写单例模式的实现逻辑。

  3. 序列化安全: 枚举类型默认实现了 Serializable 接口,并且在反序列化时保证只会创建一个实例,因此可以保证序列化和反序列化的安全性。

  4. 防止反射攻击: 枚举类型的实现方式可以防止通过反射来创建多个实例的情况,确保单例的唯一性。

  • 35
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计模式是一种经过总结、优化的、可重复使用的设计经验的总结。它是软件工程中一种解决特定问题的可复用方案。设计模式不是一成不变的,而是可以根据不同的需求进行变化,以达到最佳的效果。设计模式可以提高程序的可读性、可维护性、可扩展性,同时也可以提高程序的性能和稳定性。 设计模式可以分为三种类型:创建型模式、结构型模式和行为型模式。创建型模式用于描述对象的创建过程,结构型模式用于描述对象之间的关系,行为型模式用于描述对象的行为和交互。本篇文章将介绍一些常用的设计模式。 1. 工厂模式(Factory Pattern) 工厂模式是一种常用的创建型模式,它使用一个工厂方法来创建对象,而不是通过直接调用构造函数。工厂模式可以隐藏对象的创建过程,使代码更加灵活和易于维护。工厂模式可以分为简单工厂模式、工厂方法模式和抽象工厂模式。 2. 单例模式(Singleton Pattern) 单例模式是一种创建型模式,它保证一个类只有一个实例,并提供一个全局访问点。单例模式可以保证对象的唯一性,避免了多个实例对系统资源的浪费。 3. 代理模式(Proxy Pattern) 代理模式是一种结构型模式,它为一个对象提供一个代理,以控制对这个对象的访问。代理模式可以增加对象的安全性,降低对象的访问成本,同时也可以提高程序的灵活性和可扩展性。 4. 装饰器模式(Decorator Pattern) 装饰器模式是一种结构型模式,它动态地给一个对象添加一些额外的职责,而不需要修改这个对象的代码。装饰器模式可以避免使用子类来扩展对象的功能,从而使代码更加灵活和可扩展。 5. 观察者模式(Observer Pattern) 观察者模式是一种行为型模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生改变时,会通知所有的观察者对象,使它们能够及时更新自己的状态。 以上是五种常用的设计模式,它们在软件开发中都有着广泛的应用。设计模式可以帮助我们更好地组织代码、降低程序的耦合度、提高程序的可扩展性和可维护性,是一种非常重要的编程技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值