Java设计模式-单例模式(2)

简介: Java设计模式-单例模式(2)

单例模式(Singleton)

定义

某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。

目的

节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。

特点

1.单例类只有一个实例对象;

2.该单例对象必须由单例类自行创建;

3.单例类对外提供一个访问该单例的全局访问点;

优点:

在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

避免对资源的多重占用(比如写文件操作)。

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

结构

单例模式的主要角色如下。

·单例类:包含一个实例且能自行创建这个实例的类。

·访问类:使用单例的类。

注意点

1.单例模式是自关联关系设计。

2.字段 instance 为private,static, volatile修饰。

3.getInstance(全局访问点)为public ,static 修饰,其中涉及了 synchronized关键字的使用 。

  1. 构造函数为private(私有的)。

volatile:

    volatile关键字是为了保证线程安全的,当某个线程对共享变量只是读操作而没有写操作时,使用volatile就可以保证线程安全。volatile的作用是保证可见性和有序性,因为读操作本来就具有原子性,因此仅使用volatile就可以保证线程安全。

synchronized:

    多个线程使用同一个对象进行加锁(基于对象头加锁),可以实现线程间的同步互斥。简单地说,它的原理就是基于对象头加锁,满足原子性、可见性、有序性。

懒汉式(线程安全)

是否 Lazy 初始化:是

是否多线程安全:是

实现难度:易

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

public class LazySingleton {
//保证 instance 在所有线程中同步
private static volatile LazySingleton instance = null;
private LazySingleton() {
} //private 避免类在外部被实例化

//synchronized 修饰方法级别
public static synchronized LazySingleton getInstance() {
    //getInstance 方法前加同步
    if (instance == null) {
        instance = new LazySingleton();
    }
    return instance;
}

}
懒汉式(线程不安全)

是否 Lazy 初始化:是

是否多线程安全:否

实现难度:易

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

public class LazySingleton {
private static LazySingleton instance;
private LazySingleton (){}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
饿汉式(线程安全)
是否 Lazy 初始化:否

是否多线程安全:是

实现难度:易

描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存

public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
【推荐】双检锁/双重校验锁(DCL,即 double-checked locking)
JDK 版本:JDK1.5 起

是否 Lazy 初始化:是

是否多线程安全:是

实现难度:较复杂

描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。getInstance() 的性能对应用程序很关键。

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;
}
}
登记式/静态内部类
是否 Lazy 初始化:是

是否多线程安全:是

实现难度:一般

描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。调用getInstance()方法时才创建,达到了类似懒汉式的效果,同时又是线程安全的。

public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举
JDK 版本:JDK1.5 起

是否 Lazy 初始化:否

是否多线程安全:是

实现难度:易

优点:线程安全,不用担心反射破坏单例模式,性能高,没有任何锁。

缺点:枚举类占用内存多。

描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

public enum Singleton {
INSTANCE;
public void otherMethod() {
//处理其他功能业务
}
}
23 种设计模式不是孤立存在的,很多模式之间存在一定的关联关系,在大的系统开发中常常同时使用多种设计模式,或者模式与模式之间的组合进行生成更加强大的程序功能。

好了,关于单例模式的说明,馆长就先讲到这里,最近馆长了解到单例模式实现不仅仅是上述的几种,随着软件行业的发展,各种变种也开始流行。由于时间和精力问题,馆长就先整理这些。谢谢各位看官!!
相关文章
|
1月前
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
90 15
|
27天前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
50 0
|
2月前
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
57 0
|
3月前
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
|
3月前
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
4月前
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
45 4
|
6月前
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
150 13
|
7月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
124 6
|
6月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
73 2
|
7月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
97 4