设计模式之单例模式(创建型)

举报
yd_273762914 发表于 2020/12/03 00:43:06 2020/12/03
【摘要】 前言 本博客介绍一种创建型模式:单例模式 这是一种比较容易理解的设计模式,可以理解为创建对象的一种很好的做法。可以尽量避免创建过多的对象,给JVM造成很大的负载。 应用场景 单例模式的一些应用场景: 1、比如数据连接类,这是需要经常调用的 2、网站访问量统计的服务类,需要多次调用 3、导出导入Excel表,一些业务复杂的系统需要多次调用 … 总结起来就...

前言

本博客介绍一种创建型模式:单例模式
这是一种比较容易理解的设计模式,可以理解为创建对象的一种很好的做法。可以尽量避免创建过多的对象,给JVM造成很大的负载。

应用场景

单例模式的一些应用场景:
1、比如数据连接类,这是需要经常调用的
2、网站访问量统计的服务类,需要多次调用
3、导出导入Excel表,一些业务复杂的系统需要多次调用

总结起来就是需要经常调用的通用类,我们可以用单例模式进行很好的设计。

编程思想

单例模式涉及了两种重要的编程思想:懒加载思想和缓存思想

缓存思想:

 private static Singleton instance = null;//先放内存缓存 public static Singleton getInstance() { if (instance == null) {//内存加载不到,创建对象 instance = new Singleton(); } return instance;//内存缓存有,直接调用 }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

懒加载思想:
下面例子就是懒加载的简单应用,创建一个对象都是需要用的时候实例,尽量不要在加载类的时候就实例了,这种方法可以很好的避免给JVM增加负载。这是一种很好的编程习惯。

public static Singleton getInstance() { if (instance == null) {//对象需要用时才实例 instance = new Singleton(); } return instance; }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

单例模式实例

下面介绍几种常用的单例模式实例

1、懒汉模式
这是一种线程不安全,懒加载的方式

public class Singleton { private static Singleton instance; //定义private构造函数,使类不可以被实例 private Singleton (){} /** * 懒汉模式,线程不安全,懒加载 * @return */ public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

上面例子线程不安全,要线程安全可以加个同步锁,不过加了同步锁性能又不好了,加载慢

public class Singleton { private static Singleton instance; //定义private构造函数,使类不可以被实例 private Singleton (){} /** * 懒汉模式,线程安全,懒加载 * @return */ public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2、饿汉模式
下面介绍一下单例模式的另外一种实现方式,饿汉模式
其实现原理就是在类内部全局new一个对象,利用Java虚拟机的类加载机制,保证了线程安全,不过很明显,一创建了,就实例了单例类,会给JVM增加负载

public class Singleton { //定义private构造函数,使类不可以被实例 private Singleton (){} //加载类的时候,利用JVM的类加载机制创建对象,保证了线程安全,但是效率不好 private static Singleton instance = new Singleton(); /** * 饿汉模式,线程安全,非懒加载 * @return */ public static Singleton getInstance() { return instance; }
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3、双检锁/双重校验锁(DCL,即 double-checked locking)
下面介绍一种双检锁的实现方式,这种方式看起来稍稍比较复杂了点,不过可以实现线程安全,同时双检锁的方式可以保证性能比较高

public class Singleton { //定义private构造函数,使类不可以被实例 private Singleton (){} private volatile static Singleton instance; /** * 双检锁/双重校验锁(DCL,即 double-checked locking)线程安全,懒加载 * @return */ public static Singleton getInstance(){ if(instance == null){ synchronized (Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; }
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

4、登记式/内部类
下面用内部类的方式来实现单例模式,这种方式可以和饿汉模式来对比一下
这种方式和刚才介绍的饿汉模式类似,不过区别就是做到了懒加载,我们可以分析例子。方法就是在单例类里加个内部类,这样做就不会像饿汉模式一样,单例类一加载就实例对象。当调用getInstance方法的时候,才会调用,创建对象。这样就做到了懒加载,同时也是利用JVM保证了线程安全

public class Singleton { //定义private构造函数,使类不可以被实例 private Singleton (){} public static class SingletonHolder{ private final static Singleton INSTANCE = new Singleton(); } /** * 登记式/静态内部类,线程安全,懒加载 * @return */ public static Singleton getInstance(){ return SingletonHolder.INSTANCE; }
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

5、枚举模式
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。

/** * 枚举方式 */ public enum Singleton { INSTANCE; public void whateverMethod() { } }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

文章来源: smilenicky.blog.csdn.net,作者:smileNicky,版权归原作者所有,如需转载,请联系作者。

原文链接:smilenicky.blog.csdn.net/article/details/80019048

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。