资讯专栏INFORMATION COLUMN

Java设计模式-单例模式:单例的六种实现

番茄西红柿 / 2429人阅读

摘要:单例模式的优缺点优点单例模式在内存中只有一个实例,减少了内存开支,尤其是频繁的创建和销毁实例。单例模式对测试不利。单例模式与单一职责原则有冲突,一个类应该只实现一个逻辑,而不用关心它是否是单例的。资源源码参考设计模式之禅

原文地址:xeblog.cn/articles/16

单例模式的定义

</>复制代码

  1. 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

UML类图

单例类的构造函数是 private 内部私有的,确保外部不能通过 new 的方式创建新对象,内部自行实例化,并对外提供一个访问该单一实例的静态的方法 Instance()

单例模式的实现 普通饿汉式

</>复制代码

  1. /**
  2. * 普通饿汉式
  3. *
  4. * @author anlingyi
  5. */
  6. public class Singleton {
  7. /**
  8. * 类加载时进行实例化对象
  9. */
  10. private static final Singleton SINGLETON = new Singleton();
  11. /**
  12. * 私有构造,防止外部new对象
  13. */
  14. private Singleton() {
  15. }
  16. /**
  17. * 通过静态方法获取对象实例
  18. *
  19. * @return
  20. */
  21. public static Singleton getInstance() {
  22. return SINGLETON;
  23. }
  24. public void say() {
  25. System.out.println("普通饿汉式:Hello World!");
  26. }
  27. }

调用方式:

</>复制代码

  1. Singleton singleton = Singleton.getInstance();
  2. singleton.say();

优缺点

优点: 类加载时就进行实例化,之后的操作效率会很高。
缺点: 由于类加载时就进行实例化,如果后续不对此类进行任何操作,就会导致内存的浪费。

线程不安全的懒汉式

</>复制代码

  1. /**
  2. * 懒汉式(线程不安全)
  3. *
  4. * @author anlingyi
  5. */
  6. public class SingletonTwo {
  7. private static SingletonTwo instance;
  8. /**
  9. * 私有构造,防止外部new对象
  10. */
  11. private SingletonTwo() {
  12. }
  13. /**
  14. * 通过静态方法获取对象实例
  15. *
  16. * @return
  17. */
  18. public static SingletonTwo getInstance() {
  19. if(instance == null) {
  20. instance = new SingletonTwo();
  21. }
  22. return instance;
  23. }
  24. public void say() {
  25. System.out.println("懒汉式(线程不安全):Hello World!");
  26. }
  27. }

调用方式:

</>复制代码

  1. SingletonTwo singleton = SingletonTwo.getInstance();
  2. singleton.say();

优缺点

优点: 在第一次调用的时候才进行实例化。
缺点: 当多个线程同时进入到 if(instance == null) {...} 时,会创建多个对象。

同步锁懒汉式

</>复制代码

  1. /**
  2. * 同步锁懒汉式(线程安全,效率低)
  3. *
  4. * @author anlingyi
  5. */
  6. public class SingletonThree {
  7. private static SingletonThree instance;
  8. /**
  9. * 私有构造,防止外部new对象
  10. */
  11. private SingletonThree() {
  12. }
  13. /**
  14. * 通过静态方法获取对象实例
  15. *
  16. * @return
  17. */
  18. public static synchronized SingletonThree getInstance() {
  19. if(instance == null) {
  20. instance = new SingletonThree();
  21. }
  22. return instance;
  23. }
  24. public void say() {
  25. System.out.println("同步锁懒汉式(线程安全,效率低):Hello World!");
  26. }
  27. }

调用方式:

</>复制代码

  1. SingletonThree singleton = SingletonThree.getInstance();
  2. singleton.say();

优缺点

优点: 在第一次调用的时候才进行实例化,且线程安全。
缺点: 使用 synchronized 的方式对方法加锁,会影响效率。

双重校验锁懒汉式

</>复制代码

  1. /**
  2. * 双重校验锁懒汉式(线程安全,且多线程环境下可以保持高性能)
  3. *
  4. * @author anlingyi
  5. */
  6. public class SingletonFour {
  7. /**
  8. * volatile是为了防止指令重排序
  9. */
  10. private static volatile SingletonFour instance;
  11. /**
  12. * 私有构造,防止外部new对象
  13. */
  14. private SingletonFour() {
  15. }
  16. /**
  17. * 通过静态方法获取对象实例
  18. *
  19. * @return
  20. */
  21. public static SingletonFour getInstance() {
  22. if(instance == null) {
  23. synchronized (SingletonFour.class) {
  24. if(instance == null) {
  25. instance = new SingletonFour();
  26. }
  27. }
  28. }
  29. return instance;
  30. }
  31. public void say() {
  32. System.out.println("双重校验锁懒汉式(线程安全,且多线程环境下可以保持高性能):Hello World!");
  33. }
  34. }

调用方式:

</>复制代码

  1. SingletonFour singleton = SingletonFour.getInstance();
  2. singleton.say();

优缺点

优点: 在第一次调用的时候才进行实例化,且线程安全,效率较高。
缺点: 实现复杂,且 volatile 需要在JDK1.5之后的版本才能确保安全。

静态内部类懒汉式

</>复制代码

  1. /**
  2. * 静态内部类懒汉式
  3. *
  4. * @author anlingyi
  5. */
  6. public class SingletonFive {
  7. /**
  8. * 私有构造,防止外部new对象
  9. */
  10. private SingletonFive() {
  11. }
  12. /**
  13. * 通过静态方法获取对象实例
  14. *
  15. * @return
  16. */
  17. public static SingletonFive getInstance() {
  18. return Singleton.SINGLETON;
  19. }
  20. public void say() {
  21. System.out.println("静态内部类懒汉式:Hello World!");
  22. }
  23. /**
  24. * 静态内部类实例化对象
  25. */
  26. private static class Singleton {
  27. /**
  28. * 类加载时进行实例化对象
  29. */
  30. private static final SingletonFive SINGLETON = new SingletonFive();
  31. }
  32. }

调用方式:

</>复制代码

  1. SingletonFive singleton = SingletonFive.getInstance();
  2. singleton.say();

优缺点

优点: 只有在调用 getInstance() 方法的时候,静态内部类才会被加载,从而对主类(我们需要的类)进行实例化,即线程安全,又效率高。
缺点: 多创建一个类。

枚举类饿汉式(防止反序列化)

</>复制代码

  1. /**
  2. * 枚举类饿汉式(防止反序列化)
  3. *
  4. * @author anlingyi
  5. */
  6. public enum SingletonSix {
  7. INSTANCE;
  8. public void say() {
  9. System.out.println("枚举类饿汉式(防止反序列化):Hello World!");
  10. }
  11. }

调用方式:

</>复制代码

  1. SingletonSix singleton = SingletonSix.INSTANCE;
  2. singleton.say();

优缺点

优点: 实现简单,防止反序列化生成多个实例,且线程安全。
缺点: Enum 需在JDK1.5之后版本使用。

单例模式的优缺点 优点

单例模式在内存中只有一个实例,减少了内存开支,尤其是频繁的创建和销毁实例。

由于只生成一个实例,所以减少了系统的性能开销。

避免对资源的多重占用,例如写文件操作。

单例模式可以在系统设置全局的访问点,优化和共享资源访问。

缺点

单例模式不易扩展,若要扩展,除了修改代码外别无他法。

单例模式对测试不利。

单例模式与单一职责原则有冲突,一个类应该只实现一个逻辑,而不用关心它是否是单例的。

资源

源码

参考

《设计模式之禅》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7120.html

相关文章

  • Java设计模式单例模式单例六种实现

    摘要:单例模式的优缺点优点单例模式在内存中只有一个实例,减少了内存开支,尤其是频繁的创建和销毁实例。单例模式对测试不利。单例模式与单一职责原则有冲突,一个类应该只实现一个逻辑,而不用关心它是否是单例的。资源源码参考设计模式之禅原文地址:xeblog.cn/articles/16 单例模式的定义 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 UML类图 showImg(ht...

    番茄西红柿 评论0 收藏0
  • Java设计模式单例模式单例六种实现

    摘要:单例模式的优缺点优点单例模式在内存中只有一个实例,减少了内存开支,尤其是频繁的创建和销毁实例。单例模式对测试不利。单例模式与单一职责原则有冲突,一个类应该只实现一个逻辑,而不用关心它是否是单例的。资源源码参考设计模式之禅原文地址:xeblog.cn/articles/16 单例模式的定义 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 UML类图 showImg(ht...

    Caicloud 评论0 收藏0
  • 单例模式

    摘要:第二种懒汉式线程不安全对象为空才去实例化懒汉式是在使用的时候才会去加载,不过当多次同时去加载的时候就会存在线程安全问题。 单例模式,是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例的特殊类,通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例。 第一种:饿汉式 public class SingleEasy { private SingleEas...

    darkbug 评论0 收藏0
  • Java设计模式优化-单例模式

    摘要:单例模式概述单例模式是一种对象创建模式,用于产生一个类的具体事例。所以解决了线程安全问题参考失效原因和解决方案中单例模式的缺陷及单例的正确写法懒汉式静态内部类私有构造器获取单例的方法静态内部类持有单例作为静态属性。 单例模式概述 单例模式是一种对象创建模式,用于产生一个类的具体事例。使用单例模式可以确保整个系统中单例类只产生一个实例。有下面两大好处: 对于频繁创建的对象,节省初第一...

    eccozhou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<