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. Java中的多态

    1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal {public abstract void Say();} 子类: public class ...

  2. Android 获取meta-data中的数据

    在 Android 的 Mainfest 清单文件中,Application,Activity,Recriver,Service 的节点中都有这个的存在.很多时候我们可以通过 meta-data 来配 ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. jQuery.template.js 简单使用

    之前看了一篇文章<我们为什么要尝试前后端分离>,深有同感,并有了下面的评论: 我最近也和前端同事在讨论这个问题,比如有时候前端写好页面给后端了,然后后端把这些页面拆分成很多的 views, ...

  5. IOS FMDB 获取数据库表和表中的数据

    ios开发中,经常会用到数据库sqlite的知识,除了增,删,改,查之外,我们说说如何获取数据库中有多少表和表相关的内容. 前言 跟数据库使用相关的一般的增删改查的语句,这里就不做解释了.在网上有很多 ...

  6. Android之ContentProvider数据存储

    一.ContentProvider保存数据介绍 一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProvider是以类似数据库中表的方式将数 ...

  7. 钉钉开放平台demo调试异常问题解决:hostname in certificate didn't match

    今天研究钉钉的开放平台,结果一个demo整了半天,这帮助系统写的也很难懂.遇到两个问题: 1.首先是执行demo时报unable to find valid certification path to ...

  8. 周末聊聊IT人员的人脉观:关于帮妹子找兼职有感

    背景: 前几天,有个认识了好几年的网友,现在是大学生,在厦门读大一,说和她同学要一起到广州找兼职,看我有没有介绍. 像我这么积极热心善良的人,就说帮她找找看,结果问了几次,没消息,只好诚实的回复人家, ...

  9. CentOS 6.3下 安装 Mono 3.2 和Jexus 5.4

    最新更新参看: Centos 7.0 安装Mono 3.4 和 Jexus 5.6 2012年初写过一篇<32和64位的CentOS 6.0下 安装 Mono 2.10.8 和Jexus 5.0 ...

  10. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总

    --系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...