原文地址:https://zhuanlan.zhihu.com/p/23713957

一、概述

1、什么是单例模式?

百度百科是这样定义的:单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例

我是这样理解的:单例模式就是只允许一个实例,最开始使用它的时候是C#中,我要实例化一个A窗体,但是有个需求就是A窗体必须是唯一,不管我在B窗体操作A窗体还是C窗体中操作A窗体都是如此,这时候就使用到了单例模式

2、单例模式分类

A、懒汉单例模式:在第一次调用的时候实例化本身,在并发环境下,可能出现多个本身对象。所以线程是不安全的

B、饿汉单例模式:在类初始化时,已经自行实例化一个静态对象,所以本身就是线程安全的

C、登记单例模式:通过一个专门的类对各单例模式的单一实例进行管理和维护

3、特点

A、 单例模式类只能有一个实例

B、 单例模式类必须自己创建自己的唯一实例

C、 单例模式类必须给所有其他对象提供这一实例

二、运用

1、懒汉单例模式

/**
* 描述:懒汉单例模式<p>
* 作者: kimball <p>
* E-mail: kimballlu@foxmail.com <p>
* 日期:2016-11-16 下午4:30:32 <p>
*/
public class Singleton { /**
* 该函数限制用户主动创建实例
*/
private Singleton() {}
private static Singleton singleton = null; /**
* 获取Singleton实例(也叫静态工厂方法)
* @return Singleton
*/
public static Singleton getSingleton() {
/* 当singleton为空时创建它,反之直接返回,保证唯一性 */
if(singleton == null){
singleton = new Singleton();
}
return singleton;
} }

线程安全的懒汉单例模式

在getSingleton()添加synchronized同步

/**
* 描述:懒汉单例模式,在getSingleton()方法添加同步<p>
* 作者: kimball <p>
* E-mail: kimballlu@foxmail.com <p>
* 日期:2016-11-16 下午4:30:32 <p>
*/
public class Singleton { /**
* 该函数限制用户主动创建实例
*/
private Singleton() {}
private static Singleton singleton = null;
/**
* 获取Singleton实例,也叫静态工厂方法
* @return Singleton
*/
public static synchronized Singleton getSingleton(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
} }

双重检查锁定

ps:已修正,仍不推荐使用,感谢

江南布衣

指正

具体可参考正确使用双重检查锁定和双重检验锁失效”的问题说明

/**
* 描述:懒汉单例模式 ,双重检查锁定<p>
* 作者: kimball <p>
* E-mail: kimballlu@foxmail.com <p>
* 日期:2016-11-16 下午4:30:32 <p>
*/
public class Singleton { /**
* 该函数限制用户主动创建实例
*/
private Singleton() {} private volatile static Singleton singleton = null; /**
* 获取Singleton实例,也叫静态工厂方法
* @return Singleton
*/
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
} }

静态内部类:静态内部类比双重检查锁定和在getInstance()方法上加同步都要好,实现了线程安全又避免了同步带来的性能影响

/**
* 描述:懒汉单例模式 ,静态内部类<p>
* 作者: kimball <p>
* E-mail: kimballlu@foxmail.com <p>
* 日期:2016-11-16 下午4:30:32 <p>
*/
public class Singleton { /**
* 静态内部类
* @author kimball
*
*/
private static class LazyHolder {
// 创建Singleton实例
private static final Singleton INSTANCE = new Singleton();
} /**
* 该函数限制用户主动创建实例
*/
private Singleton() {} /**
* 获取Singleton实例,也叫静态工厂方法
* @return Singleton
*/
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
} }

2、饿汉单例模式

/**
* 描述:饿汉单例模式<p>
* 作者: kimball <p>
* E-mail: kimballlu@foxmail.com <p>
* 日期:2016-11-16 下午4:30:32 <p>
*/
public class Singleton { /**
* 该函数限制用户主动创建实例
*/
private Singleton() {} private static final Singleton singleton = new Singleton(); /**
* 获取Singleton实例,也叫静态工厂方法
* @return Singleton
*/
public static Singleton getInstance() {
return singleton;
} }

3、登记单利模式

/**
* 描述:登记单例模式<p>
* 作者: kimball <p>
* E-mail: kimballlu@foxmail.com <p>
* 日期:2016-11-16 下午4:30:32 <p>
*/
public class Singleton { // 存储需要进行维护和管理的类的实例
private static Map<String, Singleton> map = new HashMap<String, Singleton>(); /**
* 静态创建实例并添加到Map集合
*/
static {
Singleton singleton = new Singleton();
map.put(singleton.getClass().getName(), singleton);
} /**
* 该函数限制用户主动创建实例
*/
private Singleton() {}; /**
* 获取Singleton实例,也叫静态工厂方法
* @return Singleton
*/
public static Singleton getInstance(String name) {
/* 根据指定的类的名称从mao中获取实例并返回 */
return map.get(name);
} // 一个示例性的商业方法
public String about() {
return "你好,我是RegSingleton";
} public static void main(String[] args) {
Singleton singleton = Singleton.getInstance("com.Singleton");
System.out.println(singleton.about());
} }

三、结语

以上就是单例设计模式,虽然单例设计模式是23种设计模式种比较简单的设计模式。但是三个臭皮匠也能顶一个诸葛亮,它自然有它存在的道理。

设计模式说白点就是编码的一种思维(之前在学校老师一个劲儿的说思维思维,现在我也开始说,手动滑稽)

我是以生活的角度去看待编码,编码就是世界的缩小版

四、补充

上述讲的几种单例模式实现中,有一种情况下他们会重新创建对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而获得了一个实例。反序列化操作提供了readResolve方法,这个方法可以让开发人员控制对象的反序列化。在上述的几个方法示例中如果要杜绝单例对象被反序列化是重新生成对象,就必须加入如下方法:

private Object readResolve() throws ObjectStreamException{
return singleton;
}

以上摘自https://blog.csdn.net/itachi85/article/details/50510124

1、由于enum是通过继承了Enum类实现的,enum结构不能够作为子类继承其他类,但是可以用来实现接口。此外,enum类也不能够被继承。

2、enum有且仅有private的构造器,防止外部的额外构造

补充一种枚举实现的单例模式。

public enum  SingletonEnum {
INSTANCE;
}

这样就实现完了,调用如下

	@Test
void singleton(){ SingletonEnum instance = SingletonEnum.INSTANCE;
}

对于序列化和反序列化,因为每一个枚举类型和枚举变量在JVM中都是唯一的,即Java在序列化和反序列化枚举时做了特殊的规定,枚举的writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法是被编译器禁用的,因此也不存在实现序列化接口后调用readObject会破坏单例的问题。

以上摘自https://www.cnblogs.com/cielosun/p/6596475.html

如果文章对您有帮助,请记得点赞关注哟~

欢迎大家关注我的公众号<情系IT>,每日技术推送文章供大家学习参考。

java23种设计模式(三)单例模式的更多相关文章

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

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

  2. java23种设计模式之一: 单例模式(Singleton Pattern)

    单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括: 1.理解什么是单例模式.单例模式有什么优点/缺点.单例模式的应用场景: 2.再来看看Java ...

  3. java23种设计模式——三、工厂模式

    源码在我的github和gitee中获取 工厂模式 工厂模式介绍 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式.著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在J ...

  4. java23种设计模式——四、原型模式

    源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...

  5. java23种设计模式—— 一、设计模式介绍

    Java23种设计模式全解析 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模 ...

  6. java23种设计模式——五、建造者模式

    源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...

  7. java23种设计模式——八、组合模式

    目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模式 java23种设计模式-- ...

  8. java23种设计模式——七、桥接模式

    原文地址:https://www.cnblogs.com/chenssy/p/3317866.html 源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 j ...

  9. java23种设计模式 (转)

    文章在:http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html 随着自己的开发经验增加以及自己做了很多的 大专栏  jav ...

  10. java23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

随机推荐

  1. PTA A1001&A1002

    从今天起每天刷1-2题PAT甲级 第一天 A1001 A+B Format (20 分) 题目内容 Calculate a+b and output the sum in standard forma ...

  2. Spring——依赖注入(DI)详解

    声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...

  3. Eclipse中Spring Boot响应jsp的简单demo

    首先在Eclipse里新建一个maven工程,这里的打包类型和父包如果后续再去pom中添加也可以 此时的工程路径是这样的 接下来去到pom中添加相关的依赖,如果有报错maven update一下即可 ...

  4. 从零开始入门 K8s | 应用编排与管理(酒祝)

    一.需求来源 背景问题 首先来看一下背景问题.如下图所示:如果我们直接管理集群中所有的 Pod,应用 A.B.C 的 Pod,其实是散乱地分布在集群中. 现在有以下的问题: 首先,如何保证集群内可用 ...

  5. APP功能测试要点(功能测试重点)

    APP功能测试要点 1.功能性测试 根据产品需求文档编写测试用例而进行测试,包括客户端的单个功能模块以及功能业务逻辑(功能交互)如:涉及输入的地方需要考虑等价类,边界值,异常或非法等 1.1 安装与卸 ...

  6. 第八届蓝桥杯java b组第六题

    标题:最大公共子串 最大公共子串长度问题就是:求两个串的所有子串中能够匹配上的最大长度是多少. 比如:"abcdkkk" 和 "baabcdadabc",可以找 ...

  7. 品Spring:bean工厂后处理器的调用规则

    上一篇文章介绍了对@Configuration类的处理逻辑,这些逻辑都写在ConfigurationClassPostProcessor类中. 这个类不仅是一个“bean工厂后处理器”,还是一个“be ...

  8. Spring Boot 梳理 - 4个核心

    Spring Boot 魔法的核心:自动配置.起步依赖.命令行界面.Actuator 自动配置: 不用手动配置JdbcTemplate的Bean 不用手动配置DataSource的Bean Sprin ...

  9. MongoDB 学习笔记之 $push,$each,$slice组合使用

    $push使用: 使用$push给数组添加2个新成员 db.ArrayTest.updateOne({ "name" : "Bill"},{$push: {&q ...

  10. Nginx开启Gzip压缩提升页面加载速度

    1.在 nginx 的conf 目录下新建 gzip.conf 文件 #开启gzip压缩 gzip on; #设置允许压缩的页面最小字节数 gzip_min_length 1k; #申请4个单位为16 ...