本文包括以下几点↓ 结论: 意图 旨在确保类只有一个实例,并提供一个全局访问点以访问该实例。 适用性 当你希望系统中只有一个实例,并且需要从全局任何地方都能访问该实例时。 当你需要严格控制某个类的实例化过程,以确保所有代码都使用相同的实例时。 简述 单例模式的核心思想是控制对象 实现单例模式有几种方式,通过以下案例展开。 六种常见的单例模式实现方式,逐一分析它们的特点和适用场景: 源码 特点: 懒加载,在首次使用时创建实例化对象。在多线程环境下,可能会出现并发问题,导致创建多个实例。 适用场景: 单线程环境下的简单应用,对性能要求不高,且不会频繁使用单例的场景。 源码 特点: 同样是懒加载,但使用了 synchronized 关键字来保证线程安全。然而,这会造成性能下降,因为每次获取实例对象都需要加锁。 适用场景: 在多线程环境下使用,对性能要求不高的场景,或者对并发要求不是特别高的情况。 源码 特点: 在类加载时就创建实例化对象,因此不存在多线程安全问题,且访问时效率高。但可能会浪费内存,因为实例在程序启动时就创建了,即使未被使用也会占用内存。 适用场景: 对内存占用没有过多要求,且希望在程序启动时就初始化单例的场景。 源码 特点: 通过双重检查加锁,既实现了懒加载,又保证了线程安全,且在实例已创建的情况下避免了不必要的锁竞争,因此性能较高。 适用场景: 对性能要求较高,且需要懒加载的场景,特别是在多线程环境下。 源码 特点: 通过静态内部类实现了懒加载,且保证了线程安全。在类加载时并不会初始化,只有在首次调用 适用场景: 对内存占用有要求,且希望在首次使用时才初始化的场景。 源码 特点: 使用枚举类型实现单例,利用枚举的特性保证了在任何情况下都只会有一个实例存在。枚举类的实例在类加载时就会被初始化。 适用场景: 对内存占用没有过多要求,且希望简洁明了地实现单例的场景。枚举类也是线程安全的。 枚举类本身就是单例模式Singleton instance = Singleton.INSTANCE; 并且可以有多个枚举 这是实现单例模式的最佳方法,它更简洁,自动支持序列化机制,绝对防止多次实例化。但不能通过反射来调用私有构造方法。 在Spring框架中,使用到单例模式思想的地方非常多,被广泛应用于管理和创建bean实例。Spring容器默认情况下会将所有的bean都配置为单例,这意味着在整个应用程序中,每个bean都只有一个实例存在。这种默认的单例模式确保了Spring应用程序的性能和资源利用率。 在Spring上下文中,通过使用 例如:数据库连接配置类 在Spring框架中的这个单例模式是使用单例设计模式创建Bean的吗? 很显然不是。最显著的一点就是,你在项目中创建的类的构造方法是私有的吗? Spring 底层创建单例模式的Bean 使用的是BeanFactory工厂设计模式去创建的,在此别混淆了。这种Bean概念更准确的描述应该是Bean的 除此之外,Spring框架还提供了其他类型的作用域,比如 单例模式的作用主要包括以下几个方面: 简言之,单例模式在需要确保系统中某个类只有一个实例存在,并且需要提供全局访问点。它可以简化系统架构,提高代码的重用性和可维护性,同时节约系统资源,提高系统性能。但是要注意,线程是否安全的问题。 看了Spring单例作用域的Bean,应该知道一点: 设计模式不是简单地将一个固定的代码框架套用到项目中,而是一种 就单例设计模式来说,控制一个类只有一个实例,并提供一个全局访问点,掌握这个编程思想的应用才是学习设计模式的关键。设计模式
不是简单地将一个固定的代码框架套用到项目中,而是一种严谨的编程思想
,旨在提供解决特定问题的经验和指导。单例模式(Singleton Pattern)
只实例化一次
,并提供一个全局访问点
来获取该实例。这样可以确保在系统中只有一个实例,并且所有对该实例的访问都通过同一个访问点。简单案例
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}getInstance()
方法时才会初始化。
public enum Singleton {
INSTANCE;
// private Singleton(){}
public Singleton getSelf() {
return INSTANCE;
}
}
public static void main(String[] args) {
Singleton instance = Singleton.INSTANCE;
}INSTANCE,TWO;
枚举类中的INSTANCE就是Singleton对象实例,看getSelf方法不报错就知道了;枚举类的构造方法本身就是private
,放开实例中的注释结果一样;枚举中的方法
只能通过Singleton.INSTANCE.getSelf()的方式来调用,这就是单例的表现。在Spring框架中的应用??
@Bean
、@Component
、@Service
、@Repository
等注解或在配置文件中显式声明bean,Spring会自动将其配置为单例模式,即在整个应用程序中只创建一个实例。比如配置类的创建。@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase");
dataSource.setUsername("username");
dataSource.setPassword("password");
return dataSource;
}
}
单例作用域
。Prototype
原型模式,可以通过 @Scope("prototype")
注解来标注一个bean,这样每次从容器中获取该bean时,容器都会创建一个新的实例。@Component
@Scope("prototype")
public class MyPrototypeBean {
// 类的具体代码
}Prototype
原型作用域的Bean对象和原型设计模式有什么关系呢?在原型设计模式中再进行分享。总结:
严谨的编程思想
,旨在提供解决特定问题的经验和指导。