前言

上面的章节中,我们介绍了工厂模式,它是创建型模式的一种。本章我们将会介绍 单例模式 ,它也是创建型模式的一种。单例模式是我们比较常用的一个设计模式,也是最简单的一种设计模式。

单例模式

介绍:确保在一个jvm中某个类有且只有一个实例。

类图:

从上面的类图中,我们可以总结出以下几点:

  • 单例模式需要实现一个私有的构造函数,防止有外部的语句会实例化该类。
  • 单例模式需要定义一个静态成员变量,用来指向该类的唯一实例。
  • 单例模式需要定义一个静态成员方法,用来返回该类唯一的实例。

单例模式的实现

单例模式的实现方式有8种,下面让我们分别来看一看这几种实现方式的区别。

饿汉模式

代码:

public class Singleton {
private Singleton() {
    if (singleton != null) {
      throw new RuntimeException();
    }
  }
private static Singleton singleton = new Singleton();
public static Singleton initSingleton() {
return singleton;
}
}
  • 是否是懒加载:否
  • 是否线程安全:是
  • 优点:不用加锁,执行效率高。
  • 缺点:类加载时就初始化,浪费内存。

饿汉模式(静态代码块初始化)

代码:

public class Singleton {
private Singleton() {
    if (singleton != null) {
      throw new RuntimeException();
    }
  }
private static Singleton singleton;
static {
singleton = new Singleton();
}
public static Singleton initSingleton() {
return singleton;
}
}
  • 是否是懒加载:否
  • 是否线程安全:是
  • 优点:不用加锁,执行效率高。
  • 缺点:类加载时就初始化,浪费内存。

懒汉模式

import java.util.Objects;

public class Singleton {
private Singleton() {
    if (singleton != null) {
      throw new RuntimeException();
    }
  }
private static Singleton singleton;
public static Singleton initSingleton() {
if (Objects.isNull(singleton)) {
singleton = new Singleton();
}
return singleton;
}
}
  • 是否是懒加载:是
  • 是否线程安全:否
  • 优点:不用加锁,执行效率高,第一次调用时初始化,避免了浪费内存。
  • 缺点:非线程安全,多线程环境下,可能会产生多个实例。

懒汉模式(线程安全)

import java.util.Objects;

public class Singleton {
private Singleton() {
    synchronized(Singleton.class) {
      if (Objects.nonNull(singleton)) {
        throw new RuntimeException();
      }
    }
  }
private static Singleton singleton;
public static synchronized Singleton initSingleton() {
if (Objects.isNull(singleton)) {
singleton = new Singleton();
}
return singleton;
}
}
  • 是否是懒加载:是
  • 是否线程安全:是
  • 优点:第一次调用时初始化,避免了浪费内存。
  • 缺点:实现了synchronized方法,会影响执行效率。

懒汉模式(同步代码块)

import java.util.Objects;

public class Singleton {
private Singleton() {
    synchronized(Singleton.class) {
      if (Objects.nonNull(singleton)) {
        throw new RuntimeException();
      }
    }
  }
private static Singleton singleton;
public static Singleton initSingleton() {
if (Objects.isNull(singleton)) {
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
return singleton;
}
}
  • 是否是懒加载:是
  • 是否线程安全:否
  • 优点:第一次调用时初始化,避免了浪费内存。
  • 缺点:虽然实现了synchronized代码块,但是如果有多个线程同时实例化,那么有可能会产生多个实例。

双重检查模式

import java.util.Objects;

// 不能加Serializable,防止反序列化创建对象
public class Singleton {
private Singleton() {
    // 防止反射创建对象
    if (Objects.isNull(singleton)) {
      synchronized (Singleton.class) {
        if (Objects.isNull(singleton)) {
          singleton = this;
        } else {
          throw new RuntimeException();
        }
      }
    } else {
      throw new RuntimeException();
    }
  }
private static volatile Singleton singleton;
public static Singleton initSingleton() {
if (Objects.isNull(singleton)) {
synchronized (Singleton.class) {
if(Objects.isNull(singleton)) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
  • 是否是懒加载:是
  • 是否线程安全:是
  • 优点:第一次调用时初始化,避免了浪费内存。
  • 缺点:暂无

静态内部类

public class Singleton {
private Singleton() {
    if (Objects.nonNull(singleton)) {
      throw new RuntimeException();
    }
  }
public static Singleton initSingleton() {
return SingletonInstance.singleton;
} public static class SingletonInstance {
private static Singleton singleton = new Singleton();
}
}
  • 是否是懒加载:是
  • 是否线程安全:是
  • 优点:第一次调用时初始化,避免了浪费内存,效率高。
  • 缺点:暂无

枚举

public enum Singleton {
INSTANCE;
}
  • 是否是懒加载:是
  • 是否线程安全:是
  • 优点:第一次调用时初始化,避免了浪费内存,效率高。
  • 缺点:暂无

[design pattern](7) Singleton的更多相关文章

  1. Java Design Pattern(Factory,Singleton,Prototype,Proxy)

    一.Factory 设计模式: the most common pattern,create a new object ,eg. A a=new A();工厂模式的好处:工厂模式可以做到把创建对象单独 ...

  2. Learning JavaScript Design Patterns The Singleton Pattern

    The Singleton Pattern The Singleton pattern is thus known because it restricts instantiation of a cl ...

  3. Design Pattern —— Singleton

    Design Pattern —— Singleton   强力推荐枚举和类级内部类方式实现单例模式 单例模式是开发中非常常用的一种模式,简单的说,我们希望一个类永远都只有一个对象. 主要有两个用途: ...

  4. [Design Pattern] Singleton Pattern 简单案例

    Singleton Pattern, 即单例模式,用于获取类的一个对象,该对象在整个应用中是其类的唯一对象.单例模式属于创建类的设计模式. SingleObject 作为单例类,内含了一个静态私有的 ...

  5. python singleton design pattern super() 多继承

    python  singleton design pattern decorate baseclass metaclass import module super() 一.A decorator de ...

  6. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  7. 设计模式(Design Pattern)系列之.NET专题

    最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...

  8. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  9. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

随机推荐

  1. 索引之----mysql单列索引失效的情况

    使用的索引名称: 1.隐式转换导致索引失效. 由于表字段定义为vachar类型,但在查询时把该字段作为number类型 以及where条件传给mysql. 2.对索引列进行任何操作(计算(+.-.*. ...

  2. 利用ansible进行主机信息收集

    --- - hosts: myjob gather_facts: True vars: IP: "{{ ansible_default_ipv4['address'] }}" HO ...

  3. PHP:ReflectionClass

    一.简介 ReflectionClass 类报告了一个类的有关信息 ReflectionException 类继承Exception 二.常用函数 ReflectionClass::__constru ...

  4. 常用的PHP函数封装,有排序和数据库操作函数

    //二分查找 function bin_sch($array, $low, $high, $k) { if ($low <= $high) { $mid = intval(($low + $hi ...

  5. 用slot和component实现表单共用

    业务需求 在oa开发中,有许多流程,每个流程里都会有很多字段,比如流程标题.拉下选择,附件等等,有些是每个流程都会有的,有些是特有的,按常规的方法开发,就为为一个流程写一个表单,校验,提交.如果新来流 ...

  6. SQL语句中*号的缺点

    我觉得这篇博客说的比较好,参考借鉴一下:https://blog.csdn.net/weixin_44588186/article/details/87263756

  7. hadoop面试复习笔记(1)

    0.Mappereduce采用的是Master/Slaves模型 1.Hadoop是一个开源软件框架,支持支持大数据集的存储和处理.Apache Hadoop是存储和处理大数据的解决方案你是因为: ( ...

  8. 动态代理之JDK 和 CGLIB

    方式一:jdk动态代理 通过proxy类的newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHand ...

  9. CSS3之box-shadow--阴影外阴影与外发光

    基础语法 外阴影:box-shadow:X Y Npx #color; 内阴影:box-shadow:inset X Y Npx #color; 第一个属性:阴影的X轴(可以使用负值) 第二个属性:阴 ...

  10. 从零开始学MySQL(三)

    经过上两节的洗礼,我们能够连接上服务器,并成功地进入与mysql交互的会话中了.那么现在就可以发起SQL语句,让服务器来执行它了!这听起来很酷吧?接下来,我们开始学习MySQL的相关知识. 本文概览: ...