【HeadFirst 设计模式学习笔记】5 单例模式

简介: 作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.单例模式确保一个实例被创建,并且任意时刻都只有一个对象。它给了我们一个全局的访问点,又屏蔽了全局变量的缺点。

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

1.单例模式确保一个实例被创建,并且任意时刻都只有一个对象。它给了我们一个全局的访问点,又屏蔽了全局变量的缺点。可以被用来管理共享资源,比如数据库连接或线程池。特征是构造函数为私有,然后声明一个私有静态成员作为类对象,对外提供一个静态类方法创建该对象,在创建对象时会先判断是否已经创建,若是则直接返回已经创建的对象,若没有则创建新对象。

2.经典的单例模式如下:

public class Singleton {
    private static Singleton uniqueInstance;
    // other useful instance variables here
    private Singleton() {}
    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    // other useful methods here
}

这个是线程不安全的,因为在同一时刻可能两个线程都进入了getInstance中创建新的Singleton,导致唯一性不能保证。

3.多线程安全的单例模式如下:

public class Singleton {
    private static Singleton uniqueInstance;
    // other useful instance variables here
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    // other useful methods here
}

使用一个synchronized 限定符对创建实例的方法进行同步,可以完成线程安全的需求,但是若已经创建后则同步这一动作是多余且降低效率的。若程序对这部分的效率不关注则使用该方法即可。

4.若总是使用该单例模式,则可以使用“急切”方式进行单例模式调用,利用了JVM加载类时会马上创建该实例的特性,这保证了线程安全,但是这又有和全局变量一样的问题——若这个对象耗资源很大,而程序在执行中又一直没有使用它,那么就造成了资源浪费:

public class Singleton {
private static Singleton uniqueInstance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return uniqueInstance;
    }
}

5.一个比较周全的方式是用“双重检查加锁”的方式减少同步次数的同时又线程安全。注意JAVA5前不支持volatile关键字。

public class Singleton {
    private volatile static Singleton uniqueInstance;//volatile 确保当uniqueInstance初始化为Singleton的实例时,多个线程可以正确的处理uniqueInstance变量。
    private Singleton() {}
    public static Singleton getInstance() {
        if (uniqueInstance == null) {//只有第一次才会执行这里面的代码。也就是说第一次为同步,后来就是不作为了——这就是我们要的效果。
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

6.注意事项:

1)单例类不能被继承,因为Java中私有构造方法的无法扩展类。

2)和全局变量相比的优缺点,请参照“急切”和“延迟”两种单件模式实现的方式进行类比分析。

3)若使用多个类加载器,则可能导致单例失效。

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/


               作者:gnuhpc
               出处:http://www.cnblogs.com/gnuhpc/
               除非另有声明,本网站采用知识共享“署名 2.5 中国大陆”许可协议授权。


分享到:

目录
相关文章
|
7月前
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
284 15
|
9月前
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
8月前
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
151 0
|
10月前
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
253 4
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
527 13
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
178 2
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
7月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
231 16
|
7月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
234 0
|
7月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
219 0