定义
单例模式:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例
Singleton Pattern: Ensure a class has only one instance, and provide a global point of access to it
优缺点
优点:减少内存开支;减少系统性能开销;避免对系统资源的多重占用;优化和共享资源访问
缺点:不易扩展(?);不利于测试,为完成的单例模式不能使用mock虚拟;单例模式与单一职业原则有冲突
使用场景
- 生成唯一序列号
- 在整个项目中需要一个共享访问点或共享数据,如web页面上的计数器
- 创建一个对象需要消耗的资源过多,访问IO和数据库
(PS:一个典型应用,spring中,每个Bean默认都是单例的)
实现方法
Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在)
具体实现
饿汉式:无论是否使用均实例化对象
public class SingletonEager { private static final SingletonEager instance = new SingletonEager(); public static SingletonEager getInstance() { return instance; } private SingletonEager() { } }
懒汉式(最常用):在需要用到的时候才进行第一次初始化
public class SingletonLazy { private static SingletonLazy instance = null; public static SingletonLazy getInstance() { if (instance == null) { instance = new SingletonLazy(); } return instance; } private SingletonLazy() { } }
上述懒汉式存在一个问题,同步问题,多个线程同时访问该方法时,可能会实例化出多个对象,所以:
懒汉式*改1 : 给getInstance方法增加synchronized关键字
public class SingletonLazy1 { private static SingletonLazy1 instance = null; public synchronized static SingletonLazy1 getInstance() { if (instance == null) { instance = new SingletonLazy1(); } return instance; } private SingletonLazy1() { } }
承上,synchronized方法会大大拖慢代码性能,因此:
懒汉式*改2(这种形式也叫双重锁形式):将synchronized关键字放到if之后
public class SingletonLazy2 { private static SingletonLazy2 instance = null; public static SingletonLazy2 getInstance() { if (instance == null) { synchronized (SingletonLazy2.class) { if (instance == null) { instance = new SingletonLazy2(); } } } return instance; } private SingletonLazy2() { } }
小结:以上就是单例模式的几种基本写法,具体使用哪一种,就看具体使用环境的要求严格程度了。
- 如果确定该类会被经常调用到,那么直接写成饿汉式即可
- 如果该类不常被调用,对线程要求不严格,一般使用普通懒汉式即可
- 如果确定需要使用懒汉式,且对线程要求严格,那么推荐使用懒汉式*改2。但这里特别说明一下,懒汉式*改2依然可能存在同步问题,但那就已经涉及到JVM分配内存的机制问题了,此处不做那么深入的分析,如有问题,各位可参考本文最后的参考链接2
扩展模式:固定数量的单例
public class SingletonMulti { //最大实例数量 private static int maxNumOfSingleton = 2; //实例名称列表 private static ArrayList<String> nameList = new ArrayList<String>(); //实例list private static ArrayList<SingletonMulti> singletons = new ArrayList<SingletonMulti>(); private static int countNumOfSingleton = 0; static { for (int i = 0; i < maxNumOfSingleton; i++) { singletons.add(new SingletonMulti("Sample " + i)); } } private SingletonMulti() { } private SingletonMulti(String name) { nameList.add(name); } //随机获取一个单例对象 public static SingletonMulti getInstance() { Random random = new Random(); countNumOfSingleton = random.nextInt(maxNumOfSingleton); return singletons.get(countNumOfSingleton); } }
补充:最后还有一种叫做登记式单例模式,这个模式似乎在spring里用于管理单例,本人不是特别理解,在此不做详述,以后有机会看了spring的源码可能会对此做进一步探讨。有兴趣的可以看一下参考内容中列到的第3个链接单例模式详解
单例模式vs静态方法
关于这个问题,国内外都有各种讨论,对于内存分配的一些细节问题,在下实在才疏学浅,搞不清楚java底层的内存分配规则,只能结合我看到的内容,谈一下自己对用法上一些直观的看法:
- 如果你的类不需要维持任何状态, 仅仅是提供全局的访问 , 这个时候就适合用静态方法 , 这样速度也更快。反之,则使用单例
- 单例支持延迟加载 , 而静态方法则不支持这样的特性 , 对于重量级的对象, 延迟加载就很重要
- 单例对于静态方法的另一个优点是更加面向对象,对于单例你可以使用继承和多态
参考内容:
- 《设计模式之禅》秦小波
- http://devbean.blog.51cto.com/448512/203501/ 深入java单例模式
- http://www.cnblogs.com/whgw/archive/2011/10/05/2199535.html java单例模式详解
- http://blog.csdn.net/johnny901114/article/details/11969015 单例模式vs静态方法
相关推荐
内容概要:本文档介绍了三个经典的软件设计模式——单例模式(Singleton Pattern)、工厂模式(Factory Pattern)以及观察者模式(Observer Pattern)的具体实现,并给出了带有详细注释的C++代码范例。对每个设计模式都有...
编程选择题40道:设计模式:单例、工厂与观察者模式的实现.Tex.docx
本文将详细探讨两种重要的设计模式:单例模式和工厂模式,并结合视频教程与代码示例,帮助读者深入理解这两种模式的实现原理和应用场景。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例并提供...
单例模式有多种实现方式,其中比较常见的有饿汉式、懒汉式、双重检查锁定等。 工厂设计模式是一种创建型设计模式,它的主要目标是将对象的创建和使用分离,使得代码更具有可维护性和可扩展性。该模式通常会定义一个...
本文将聚焦于创建型设计模式,特别是单例模式和原型模式,这两种模式在对象的创建方面扮演着重要的角色。 单例模式是一种限制类实例化次数的设计模式,确保在整个应用程序中,一个类只有一个实例存在。这在某些场景...
"设计模式单例模式和工厂模式综合应用"的主题聚焦于两种常用的设计模式:单例模式和工厂模式,并探讨它们如何协同工作来实现高效、灵活的代码结构。这个主题尤其适用于Java编程语言,因为Java的面向对象特性使得设计...
单例模式主要有懒汉式和饿汉式两种实现,饿汉式不会有线程安全的问题,但是提前构造对象占用了一定的资源,如果对内存要求较低的场景可以使用饿汉式实现;懒汉式应使用DCL机制来避免多线程竞争资源的问题,并且懒汉...
本文实例讲述了JS 设计模式之:单例模式定义与实现方法。分享给大家供大家参考,具体如下: 良好的设计模式可以显著提高代码的可读性,降低复杂度和维护成本。笔者打算通过几篇文章通俗地讲一讲常见的或者实用的设计...
02_JavaSE面试题:单例设计模式
本资源“一例读懂设计模式-单例模式、简单工厂模式.zip”旨在帮助初学者通过实例深入理解这两种重要设计模式:单例模式和简单工厂模式。以下是关于这两个模式的详细讲解。 1. **单例模式**: 单例模式是一种限制类...
**Java设计模式:单例模式详解** 单例模式是软件设计中的一种常见模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式在控制资源的共享、提高性能或协调多个组件之间的交互等方面有着广泛的应用。 ##...
软件体系结构实验报告
本项目涵盖了四种常见的设计模式:单例模式、工厂模式、动态代理和适配器模式。下面将详细阐述这四种设计模式的概念、作用以及在实际项目中的应用。 **1. 单例模式** 单例模式是一种限制类实例化次数为一个的设计...
单例模式的实现饿汉式懒汉式线程安全的懒汉式登记式单例模式的优缺点单例模式的优点单例模式的缺点 单例模式是23个模式中比较简单的模式,应用也非常广泛 什么是单例模式? 单例模式的定义: Ensure a class ...
在给定的标题和描述中,我们关注的是两种重要的设计模式:单例模式和观察者模式。 首先,让我们深入了解单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。这种模式在资源管理、缓存、...
【设计模式概述】 ...总的来说,单例模式、工厂模式和观察者模式都是Java中非常实用的设计模式,它们在实际开发中有着广泛的应用。理解并熟练掌握这些模式,可以帮助开发者编写出更加高效、可维护的代码。
单例模式是软件设计模式中的一种经典模式,它主要用于控制类的实例化过程,确保一个类在整个应用程序中只有一个实例存在。这种模式在Java编程中非常常见,特别是在需要频繁实例化然后销毁的对象,或者需要共享资源的...
单例模式(Singleton Pattern)作为创建型模式中的一种,旨在确保一个类在系统中只有一个实例,并提供全局访问点。
1. 单例模式: 单例模式确保一个类只有一个实例,并提供全局访问点。在Java等编程语言中,通常通过私有构造函数和静态工厂方法来实现。这种模式常用于控制资源的共享,如数据库连接或线程池。 2. 简单工厂模式: ...
在这个文档中,我们关注的是三种设计模式:单例模式、适配器模式和工厂模式。 首先,单例模式是一种确保一个类只有一个实例并提供一个全局访问点的设计模式。这种模式的核心在于控制类的实例化过程,确保在任何情况...