单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括:

1、理解什么是单例模式、单例模式有什么优点/缺点、单例模式的应用场景;

2、再来看看Java单例模式的6种代码实现方式、每种实现方式有什么需要注意的;

3、后面再来了解Java单例模式其他值得关注的地方,如比较静态方法、以及Java反射、反序列化、垃圾回收的影响等。

1、什么是单例模式

1-1、模式理解

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

UML结构图:

    

模式角色:

一个类使用了单例模式,称该类为单例类,如图中的Singleton。

单例模式三要点:

(1)、单例类只能有一个实例

这是最基本的,真正做到整个系统中唯一并不容易,通常还要考虑反射破坏、序列化/反序列化、对象垃圾回收等问题。

(2)、单例类必须自己创建自己的唯一实例

通常给实例构造函数protected或private权限。

(3)、单例类必须给所有其他对象提供这一实例

通常定义静态方法getInstance()返回。

1-2、特点

优点:

(1)、提供了对唯一实例的受控访问,避免对资源的多重占用。

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

(3)缩小名空间,避免全局变量污染空间,但比类操作更灵活。

缺点:

(1)、由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。

(2)、 单例类的职责过重,在一定程度上违背了"单一职责原则"。

因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。 所以也不应过多使用单例模式。

1-3、应用

单例模式是一种对象创建型模式,用来编写一个类,在整个应用系统中只能有该类的一个实例对象。

常见应用场景:

线程池、缓存、日志、配置文件、打印机/显卡等硬件设备的驱动程序对象等等。

JDK中的一些应用:

   java.lang.Runtime#getRuntime()

    java.text.NumberFormat#getInstance()

   java.awt.GraphicsEnvironment#getLocalGraphicsEnvironment()

2、单例模式实现示例

2-1、饿汉式(简单可用)

Lazy 初始化:否;

多线程安全:是;

描述:

这种方式比较常用,它基于JVM的类加载器机制避免了多线程的同步问题,对象在类装载时就实例化,所以称为饿汉式。

优点:没有加锁,执行效率会提高。

缺点:没有Lazy初始化,可能有时候不需要使用,浪费内存。

代码实例:

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton (){}

    public static Singleton getInstance() {
return instance; }

2-2、懒汉式(线程不安全,不可用)
      Lazy 初始化:是;

多线程安全:否;

描述:

能够在getInstance()时再创建对象,所以称为懒汉式。这种实现最大的问题就是不支持多线程。因为没有加锁同步。

代码实例:

public class Singleton {

    private static Singleton instance;

    private Singleton (){}

    public static Singleton getInstance() {

        if (instance == null) {
instance = new Singleton();
} return instance;
}

2-3、同步方法的懒汉式(同步方法效率低,不推荐)

Lazy 初始化:是

多线程安全:是

描述:

  除第一次使用,后面getInstance()不需要同步;每次同步,效率很低。

代码实例:

public class Singleton {

    private static Singleton instance;

    private Singleton (){}

    public static synchronized Singleton getInstance() {

        if (instance == null) {
instance = new Singleton();
} return instance;
}

2-4、双重校验锁(可用)
      Lazy 初始化:是;

多线程安全:是;

描述:

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

实例变量需要加volatile 关键字保证易变可见性,JDK1.5起才可用。

代码实例:

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;
}

2-5、静态内部类(推荐)

Lazy 初始化:是;

多线程安全:是;

描述:

同样利用了JVM类加载机制来保证初始化实例对象时只有一个线程,静态内部类SingletonHolder 类只有第一次调用 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;
}

2-6、枚举(《Effective Java》推荐,不常见)

Lazy 初始化:否;

多线程安全:是;

描述:

从Java1.5开始支持enum特性;无偿提供序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候。

不过,用这种方式写不免让人感觉生疏,这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。

代码实例

public enum Singleton {

    //定义一个枚举的元素,就代表Singleton实例
INSTANCE; /*
**假如还定义有下面的方法,调用:Singleton.INSTANCE.doSomethingMethod();
*/ public void doSomethingMethod() { }

2-7、小结

以上6种单例实现方式,不是线程安全的不能用,至于是否需要延时加载,看情况而定。

一般情况下,使用最基本、最简单的第一种饿汉式就行了(JDK中有不少使用该种方式),需要延时加载的使用静态内部类方式,需要高安全性的可以使用第6种枚举方式。

java23种设计模式之一: 单例模式(Singleton Pattern)的更多相关文章

  1. 二十四种设计模式:单例模式(Singleton Pattern)

    单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...

  2. 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)

    原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...

  3. 设计模式之单例模式(Singleton Pattern)

    单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...

  4. 【设计模式】单例模式 Singleton Pattern

    通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance)  的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...

  5. Java23种设计模式之单例模式

    一.单例模式简介 单例模式是Java设计模式中常见的一种模式.主要分为懒汉式单例.饿汉式单例.登记式单例: 单例模式的特点:  1.单例类只能有一个实例:  2.单例类必须自己创建自己的唯一的实例: ...

  6. 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)【转】

    介绍 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例 保证一个类仅有一个实例. Singleton using System; using System.Collections.Gene ...

  7. Java 设计模式(三)-单例模式(Singleton Pattern)

    1     概念定义 1.1   定义 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 1.2   类型 创建类模式 1.3   难点 1)多个虚拟机 当系统中的单例类被拷贝运行在多 ...

  8. python 设计模式之单例模式 Singleton Pattern

    #引入 一个类被设计出来,就意味着它具有某种行为(方法),属性(成员变量).一般情况下,当我们想使用这个类时,会使用new 关键字,这时候jvm会帮我们构造一个该类的实例.这么做会比较耗费资源. 如果 ...

  9. 【UE4 设计模式】单例模式 Singleton Pattern

    概述 描述 保证一个类只有一个实例 提供一个访问该实例的全局节点,可以视为一个全局变量 仅在首次请求单例对象时对其进行初始化. 套路 将默认构造函数设为私有, 防止其他对象使用单例类的 new运算符. ...

随机推荐

  1. PHPMailer发送邮件(一)

    Github 地址:(已更新,适用于旧版) PHPMailer : https://github.com/PHPMailer/PHPMailer 一.基本要求 Web访问正常(apache可以正常访问 ...

  2. 天梯赛 L2-014 列车调度 (模拟)

    火车站的列车调度铁轨的结构如下图所示. Figure 两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道.每趟列车从入口可以选择任意一条轨道进入,最后从出口 ...

  3. 数组中的each 和 jquery 中的 each

    数组的实例上都有一个叫做 forEach 的方法,这个方法定义在 Array.prototype 上,所以数组的所有实例都可以使用 forEach 这个方法. forEach 方法的语法结构如下: v ...

  4. mysql的一些规范

    我司的mysql规范,值得牢记 一.禁止内容 表字段类型 不推荐使用enum,set,blob,text等类型 表中所有字段都不能为空,需要设置not null属性,可以给默认值 表的主键列值禁止被更 ...

  5. 大数据系列之Hadoop框架

    Hadoop框架中,有很多优秀的工具,帮助我们解决工作中的问题. Hadoop的位置 从上图可以看出,越往右,实时性越高,越往上,涉及到算法等越多. 越往上,越往右就越火…… Hadoop框架中一些简 ...

  6. Java Web 远程调试

    Java Web 远程 调试 Tomcat 下载压缩版服务器 环境:Tomcat.Eclipse,做远程调试我们并不需要其他特殊插件 1.配置Tomcat/bin/startup.bat 在前面增加代 ...

  7. ireport报表制作, 通过节点、产品类型来判断,当该节点审核通过之后,报表相对应的审核意见及签名 显示相对应的内容

    1.代码①  (与本内容相关的代码:7~36)           以下类似 $P{P_XXXX} :均为页面端的传入参数 select so.sale_order_no as sale_order_ ...

  8. MongoDB权威指南--笔记

    mongodb并不具备一些在关系型数据库中很普遍的功能,如连接和复杂的多行事务. 集合-->文档-->id id在文档所属的集合中是唯一的. db.help()查看数据库级别的帮助,db. ...

  9. [BZOJ3672][Noi2014]购票 斜率优化+点分治+cdq分治

    3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1749  Solved: 885[Submit][Status][ ...

  10. matplotlib 练习

    官网 vamei的博客还是读了就秒懂,很妙, matplotlib核心剖析 官网翻译也不错,但缺少了 Logarithmic and other nonlinear axis对数等非线性轴  这一模块 ...