Java设计模式之单例模式理解
前言
本片博客主要记录Java23种设计模式中的创建型模式中的单例模式。单例模式可分为两类,一种是饿汉式,一种是懒汉式。饿汉式的三种设计方式(静态变量方式、静态代码块方式、枚举方式),懒汉式(单锁检查方式、双锁检查方式、静态内部类方式),以及破坏单例模式的两种方式:序列化反序列化,反射。
设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性

单例模式结构
私有的构造方法【核心】
私有的、静态的实例化变量应用
提供一个公有的、静态的获取类实例对象方法
单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。它提供了一种创建对象的最佳方式。
单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
饿汉式
静态变量方式
- 直接在创建对象时赋值
package hello;
public class Hello {
public static void main(String[] args) {
//只能通过getSingleton方法获取,不能通过new方法创建
Singleton singleton = Singleton.getSingleton();
Singleton singleton11 = Singleton.getSingleton();
//通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton11.hashCode());
}
}
class Singleton{
//私有构造方法,这样外界就不能创建了
private Singleton(){
}
//自己创建一个对象
private static Singleton singleton = new Singleton();
//给外界提供一个方法用于访问
public static Singleton getSingleton(){
return singleton;
}
}
静态代码块方式
- 在静态代码块里赋值
package hello;
public class Hello {
public static void main(String[] args) {
//只能通过getSingleton方法获取,不能通过new方法创建
Singleton singleton = Singleton.getSingleton();
Singleton singleton11 = Singleton.getSingleton();
//通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton11.hashCode());
}
}
class Singleton{
//私有构造方法,这样外界就不能创建了
private Singleton(){
}
//自己创建一个对象,但是不实例
private static Singleton singleton;
//通过静态代码块赋值
static {
singleton = new Singleton();
}
//给外界提供一个方法用于访问
public static Singleton getSingleton(){
return singleton;
}
}
枚举方式
由于上面检测代码相同,就不在这里重复复制了。
只需要把class Singleton改为下面就行了
enum Singleton{
SINGLETON;
}
懒汉式
单锁检查模式
package hello;
public class Hello {
public static void main(String[] args) {
Singleton singleton = Singleton.getSingleton();
Singleton singleton11 = Singleton.getSingleton();
//通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton11.hashCode());
}
}
class Singleton{
//私有构造方法,这样外界就不能创建了
private Singleton(){ }
//自己声明一个对象
private static Singleton singleton;
//给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
//判读singleton是否为null,如果是null就创建,否者直接返回
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
双重检查锁模式
上面的验证都是一样的,这里只显示Singleton类就行
class Singleton{
//私有构造方法,这样外界就不能创建了
private Singleton(){ }
//自己声明一个对象
private static volatile Singleton singleton;
//给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
//判读singleton是否为null,如果是null就创建,否者直接返回
if (singleton == null){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
静态内部类实现
静态内部类单例模式是一种优秀的单例模式,是比较常用的单例模式。在没有加任何锁时保证线程安全,并且没有任何性能影响和空间浪费。
在加载Singleton时不会初始化singleton,只有第一次调用getSingleton()时。JVM加载SingletonHolder初始化singleton。
class Singleton{
//私有构造方法,这样外界就不能创建了
private Singleton(){ }
//定义一个静态内部类
private static class SingletonHolder{
//只会初始化一次
private static final Singleton singleton= new Singleton();
}
//给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
return SingletonHolder.singleton;
}
}
破坏单例模式
- 破坏单例模式的方式有两种一种是序列化反序列化,另一种是反射,这里我们指记录反射
- 道高一尺,魔高一丈。有模式就会有破坏,有破坏还会有防破坏,但是还有反反破坏。这里面就多了。
通过反射破坏单例模式
package hello;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Hello {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Singleton字节码对象
Class<Singleton> singletonClass = Singleton.class;
//获取无参构造方法
Constructor<Singleton> declaredConstructor = singletonClass.getDeclaredConstructor();
//取消访问检查
declaredConstructor.setAccessible(true);
//创建Singleton对象
Singleton singleton = (Singleton) declaredConstructor.newInstance();
Singleton singleton1 = (Singleton) declaredConstructor.newInstance();
//通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton1.hashCode());
}
}
class Singleton{
//私有构造方法,这样外界就不能创建了
private Singleton(){ }
//定义一个静态内部类
private static class SingletonHolder{
//只会初始化一次
private static final Singleton singleton= new Singleton();
}
//给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
return SingletonHolder.singleton;
}
}
单例模式优缺点
优点:
- 单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建销毁时,而且创建或销毁时性能又无法优化,单例模式就非常明显了
- 单例模式只生成一个实例,减少系统的性能开销
- 单例模式可以避免对资源的多重占用
- 单例模式可以在系统设置全局的访问点,优化和共享资源访问
缺点: - 不适用于变化的对象
- 由于单例模式没有抽象层,所以扩展困难
- 单例类的职责过重,在一定程度上违背了“单一职责原则”
- 单一职责原则:一个类,应该只有一个职责
Java设计模式之单例模式理解的更多相关文章
- 折腾Java设计模式之单例模式
博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...
- java 设计模式之单例模式
-------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...
- Java设计模式之单例模式(七种写法)
Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...
- Java 设计模式之单例模式(一)
原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...
- java设计模式1——单例模式
java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...
- java设计模式之单例模式你真的会了吗?(懒汉式篇)
java设计模式之单例模式你真的会了吗?(懒汉式篇) 一.什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...
- java设计模式之单例模式(几种写法及比较)
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
- [转]JAVA设计模式之单例模式
原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...
- java设计模式之三单例模式(Singleton)
单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔 ...
随机推荐
- opencv笔记-SimpleBlobDetector
通用的 Blob 检测方法包括:Laplacian of Gaussian(LoG), Difference of Gaussian(DoG), Derterminant of Hessian(DoH ...
- Solution -「AGC 016F」Games on DAG
\(\mathcal{Description}\) Link. 给定一个含 \(n\) 个点 \(m\) 条边的 DAG,有两枚初始在 1 号点和 2 号点的棋子.两人博弈,轮流移动其中一枚棋 ...
- 痞子衡嵌入式:对比MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异. 近期有 i.MXRT 客户在集成 OTA SBL ...
- 树莓派GPIO开发(二)RGB模块-PWM调节
配置环境 系统:Raspbian11(官方64位) 设备:树莓派CM4 一.PWM简单介绍 全称:Pulse-width modulation,脉冲宽度调制,简单的数模转换方法 1.基本原理 脉冲宽度 ...
- 面试突击25:sleep和wait有什么区别
sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应,并 ...
- Java ClassLoader 学习笔记
参考 Java类加载器(ClassLoader)
- 查看jQuery版本号
1. 看源码 2. 用方法 console.log($().jquery) console.log($.fn.jquery)
- CobaltStrike逆向学习系列(10):TeamServer 启动流程分析
这是[信安成长计划]的第 10 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 基本校验与解析 0x02 初始化 0x03 启动 Listeners 在之前的分析中,都是针对 Cob ...
- (二)scrapy 中如何自定义 pipeline 下载图片
这里以一个很简单的小爬虫为例,爬取 壹心理 网站的阅读页面第一页的所有文章及其对应的图片,文章页面如下: 创建项目 首先新建一个 scrapy 项目,安装好相关依赖(步骤可参考:scrapy 安装及新 ...
- python基础之序列类型的方法——列表&元组
Hello大家好,我是python学习者小杨同学,上次跟大家分享关于python的数值类型和序列类型,本次就承接上一节的内容,说一说序列类型的方法. 序列类型的方法,简单的来说就是四个字:增删改查.随 ...