从原理到实践:面向对象设计中的经典模式-单例模式
在Java中,单例模式是一种设计模式,它保证一个类只有一个实例,并提供全局访问点以便其他对象可以访问该实例。实现单例模式的关键在于确保只有一个对象被创建并且该对象不会被多次实例化,保证被创建一次,节省系统开销。
5.1、单例实现方式
5.2、实现代码
- 饿汉式
- 懒汉式
- 懒汉式+Synchronized
- 双重校验
- 静态内部类
- 枚举(推荐方式)
在Java中,使用枚举实现单例模式是一种非常简洁和安全的方式。在枚举中,每个枚举常量都是该枚举类型的唯一实例。因此,只需要将单例对象定义为一个枚举类型,就可以保证它是线程安全的,并且只有一个实例。
以下是使用枚举实现单例模式的示例代码:
package com.hanko.designpattern.singleton;
public enum Singleton {
INSTANCE;
public void doSomething() {
// 单例对象的方法
}
}
在上面的代码中,Singleton是一个枚举类型,其中只定义了一个枚举常量INSTANCE。由于枚举常量在Java中是唯一的,因此INSTANCE就是Singleton的唯一实例。
使用枚举实现单例模式有以下优点:
- 线程安全:枚举常量在Java中确保是线程安全的,并且只会被实例化一次。
- 简洁易懂:相比其他实现方式,枚举实现单例模式更加简洁易懂。
- 防止反射攻击:由于枚举类型没有构造方法,因此无法通过反射来创建枚举常量的多个实例。
综上所述,使用枚举实现单例模式是一种安全、简单和高效的方式。
5.3、相关问题
1)什么是单例模式?
单例模式是一种设计模式,它保证一个类只有一个实例,并提供一个全局访问点以便其他对象可以访问该实例。
2)如何实现单例模式?
常见的单例模式实现方式包括饿汉式、懒汉式、双重检查锁定和静态内部类等。其中,饿汉式和静态内部类方式都是线程安全的,而懒汉式和双重检查锁定需要考虑多线程环境下的线程安全问题。
3)为什么使用单例模式?
使用单例模式可以确保在整个应用程序中只有一个实例存在,并且该实例能够被全局访问。这样可以避免创建过多的对象,节省系统资源,并且能够方便地管理全局状态。
4)单例模式有哪些优缺点?
优点:
- 单例模式可以确保只有一个实例存在,避免了创建过多的对象浪费系统资源。
- 可以方便地管理全局状态,消除重复的数据读取/写入等操作。
缺点:
- 单例模式可能会增加代码的复杂度和理解难度。
- 在多线程环境下,需要考虑线程安全问题。
- 单例模式可能会对代码的可测试性产生影响。
5)如何保证单例模式的线程安全?
可以使用synchronized关键字、volatile关键字、静态内部类等方式来保证单例模式的线程安全。其中,饿汉式和静态内部类方式是最常见的线程安全实现方式。
5.4、相关应用
在Spring框架中,单例模式被广泛应用于Bean的管理和实例化过程中。默认情况下,Spring容器会将所有的Bean都设置为单例模式,并且在第一次被访问时进行实例化。
具体来说,Spring中单例模式的应用有以下几个方面:
1)Bean的作用域:默认情况下,Spring中的Bean都是单例的,也就是说它们只会被实例化一次,并且可以被多个对象共享。除了单例之外,Spring还支持原型、请求、会话和全局会话等多种作用域。
@Component // 默认是单例的
public class MyBean {
// ...
}
2)生命周期回调:在Bean的生命周期中,Spring提供了多个回调方法,包括初始化前、初始化后、销毁前和销毁后等。通过实现这些回调方法,可以对Bean的生命周期进行管理,从而提高应用程序的可靠性和稳定性。其中,在单例模式下,Bean的初始化和销毁只会发生一次。
@Component
public class MyBean implements InitializingBean, DisposableBean {
// ...
@Override
public void afterPropertiesSet() throws Exception {
// Bean初始化完成后的操作
}
@Override
public void destroy() throws Exception {
// Bean销毁前的操作
}
}
单例模式在Spring中被广泛应用于Bean的管理和实例化过程中,并且通过作用域、延迟初始化和生命周期回调等特性,提供了更加灵活和可靠的Bean管理方式。
==================================
如果文章对你有帮助,不要忘记加个关注、点个赞!!!
转载自:https://juejin.cn/post/7226162806142861368