1. 名称

单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类。单例模式是一种对象创建型模式。

2. 问题

在有些时候,对于某个类,我们无需创建多个它的实例。站在资源利用的角度讲,单例能够节省系统资源;站在面向对象设计的角度讲,有些类确实只应该存在一个实例。例如,一个资源管理器类(比如Windows的资源管理器),它封装着系统的一些数据信息,它的作用就是封装这些数据信息,然后提供一些操作数据的方法,供调用者调用。我们是没有必要创建出多个它的实例的(还是以Windows的资源管理器为例,正常情况下你只能打开一个它的窗口)。

3. 解决方案

实现单例模式的方案有很多,下面给出几种常见的方案:

(1) 懒汉式(线程不安全)

Java代码如下:

public class Singleton {

    private static Singleton instance;

    private Singleton() {
} public static Singleton getInstance() {
return instance == null ? new Singleton() : instance;
}
}

代码很简单,算是最基本单例模式。具有懒加载特点,即在getInstance方法调用时,才初始化instance,但其只能在单线程中达到单例效果,在多线程中可能会出现创建多个实例的问题。

(2) 懒汉式(线程安全)

Java代码如下:

public class Singleton {

    private static Singleton instance;

    private Singleton() {
} public synchronized static Singleton getInstance() {
return instance == null ? new Singleton() : instance;
}
}

由于(1)中给出的懒汉模式的getInstance方法没有同步,而达不到单例的目的,于是有了(2)中线程安全的懒汉模式。它与(1)的区别仅仅在getInstance()方法前加了synchronized关键字。但随之而来的是效率低的问题,事实上,在大部分情况下,getInstance方法是不需要同步。

(3) 饿汉式(线程安全)

Java代码如下:

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
} public synchronized static Singleton getInstance() {
return instance;
}
}

这种方式利用了classLoder的特点,在类装载时就初始化instance,而在getInstance中直接返回instance,避免了多线程安全问题。缺点是,在类装载时就实例化对象,而不能进行懒加载。

除了上面的方法外,有时候,还用静态代码块来初始化instance,与上述方法类似。

public class Singleton {

    private static Singleton instance;

    static{
instance = new Singleton();
} private Singleton() {
} public synchronized static Singleton getInstance() {
return instance;
}
}
(4) IoDH(Initialization on Demand Holder线程安全)
public class Singleton {

    private static class Holder {
private final static Singleton instance = new Singleton();
} private Singleton() {
} public synchronized static Singleton getInstance() {
return Holder.instance;
}
}

这种方式兼具了以上两种方式的优点,既能够懒加载(只有在调用getInstance方法时,系统才会装载Holder类,从而实例化Instance),又是线程安全的。

(5) 枚举
public enum Singleton {
INSTANCE;
}

利用枚举来达到单例的目的,见的比较少。

(6) 双重检查锁定(Double-check Locking线程安全)
public class Singleton {

    private static Singleton instance;

    public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

这种方法是对(2)中懒加载方式的改进。它不是将整个getInstance方法锁定,而是利用了同步代码块,缩小了同步范围,提高效率。之所以使用两层判断,原因如下:

使用第一个判断,可以避免大多数不需要同步的情况发生阻塞。如果没有该判断,与直接锁定方法无异;第二个判断是基本的判断,判断是否实例化。

单例模式——创建型模式01的更多相关文章

  1. [C#]设计模式-单例模式-创建型模式

    单例模式用于在整个软件系统当中保持唯一实例,在 C# 当中最能够体现此概念的就是静态类,静态类的生命周期是跟随整个程序,并且在整个程序中仅保有一个实例. 不过在这里我们不再详细阐述单例模式与静态类有什 ...

  2. Sington单例模式(创建型模式)

    一.使用Sington单例模式的动机(Motivation) 在软件系统中,经常有一些特殊的类,必须保证它们只有一个实例,才能保证它的逻辑正确性.以及良好的效率. 大多数类用的是常规的构造器,所以往往 ...

  3. 设计模式01: Singleton 单例模式(创建型模式)

    Singleton 单例模式(创建型模式) 动机(Motivation)当进行软件开发是会有这样一种需求:在系统中只有存在一个实例才能确保它们的逻辑正确性.以及良好的效率.这应该是类设计者的责任,而不 ...

  4. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  5. [19/04/22-星期一] GOF23_创建型模式(单例模式)

    一.概念 <Design Patterns: Elements of Reusable Object-Oriented Software>(即后述<设计模式>一书),由 Eri ...

  6. java架构之路-(设计模式)五种创建型模式之单例模式

    设计模式自身一直不是很了解,但其实我们时刻都在使用这些设计模式的,java有23种设计模式和6大原则. 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可 ...

  7. Java设计模式 - 单例模式(创建型模式)

    单例模式我在上学期看一些资料时候学习过,没想到这学期的软件体系结构就有设计模式学习,不过看似篇幅不大,介绍得比较简单,在这里我总结下单例模式,一来整理之前的笔记,二来也算是预习复习课程了. 概述 单例 ...

  8. Java设计模式——单例模式(创建型模式)

    概述   单例模式保证对于每一个类加载器,一个类仅有一个实例并且提供全局的访问.其是一种对象创建型模式.对于单例模式主要适用以下几个场景: 系统只需要一个实例对象,如提供一个唯一的序列号生成器 客户调 ...

  9. Java设计模式之创建型模式

    创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类

随机推荐

  1. 【每日一linux命令4】常用参数:

     下面所列的是常见的参数(选项)义: --help,-h                              显示帮助信息 --version,-V                        ...

  2. python程序生成平均脸

    简介 项目代码https://github.com/LiuRoy/pokerface 原文链接http://www.cnblogs.com/lrysjtu/p/5492547.html 写这个项目的本 ...

  3. 前端学HTTP之日志记录

    前面的话 几乎所有的服务器和代理都会记录下它们所处理的HTTP事务摘要.这么做出于一系列的原因:跟踪使用情况.安全性.计费.错误检测等等.本文将谥介绍日志记录 记录内容 大多数情况下,日志的记录出于两 ...

  4. C++的内存泄漏检测

    C++大量的手动分配.回收内存是存在风险的,也许一个函数中一小块内存泄漏被重复放大之后,最后掏空内存. 这里介绍一种在debug模式下测试内存泄漏的方法. 首先在文件的开头以确定的顺序写下这段代码: ...

  5. Hawk 6. 编译和扩展开发

    Hawk是开源项目,因此任何人都可以为其贡献代码.作者也非常欢迎使用者能够扩展出更有用的插件. 编译 编译需要Visual Stuido,版本建议使用2015, 2010及以上没有经过测试,但应该可以 ...

  6. 香蕉云APP,2016下半年开发日记

    2016-6-17  数据库设计不应该过多依赖范式,适度的冗余可以加快搜索速度,在服务器的配置还可以的情况下,可以采用冗余来解决查找慢的问题.还一个是要选择好数据库引擎,例如 InnoDB 和 myi ...

  7. SDWebImage源码解读 之 UIImage+GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  8. 编写高质量代码:改善Java程序的151个建议(第6章:枚举和注解___建议88~92)

    建议88:用枚举实现工厂方法模式更简洁 工厂方法模式(Factory Method Pattern)是" 创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其它子类" ...

  9. StringUtils的isBlank与isEmply

    1.public static boolean isEmpty(String str) 判断某字符串是否为空,为空的标准是 str==null 或 str.length()==0 StringUtil ...

  10. 两个变量交换的四种方法(Java)

    对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) class TestEV //创建一个类 { public static ...