前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式学习笔记之单例模式

设计模式学习笔记之单例模式

作者头像
海加尔金鹰
发布2020-06-09 10:11:10
2910
发布2020-06-09 10:11:10
举报

前言

这是一篇学习笔记,内容很多是来源于网上的资料,按照自己学习进行的总结。 我的个人博客:海加尔金鹰

什么是单例模式

定义:一个类在系统当中只存在一个实例,每次获取到这个类的实例都是同一个。主要用于处理系统当中某个频繁创建和摧毁的类。 特点 :

  • 单例类只有一个实例对象
  • 该单例对象必须由单例类自行创建
  • 单例类对外提供一个访问该单例的全局访问点。

单例模式的实现

单例模式的核心代码:构造函数私有化,提供对外访问的方式。

单例模式的实现方式有很多种,我这里就只记录推荐使用的方式:

枚举

代码语言:javascript
复制
public enum Singleton {
    INSTANCE;
}

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。^1

这个我感觉是用来面试装逼的,记得以前和朋友们聊面试的时候,开玩笑的说:面试不要慌,先写个单例模式在说。至于反序列化重新创建对象的问题,目前没有遇见过。 讲真的如果不是专门学习单例模式的话,我都不知道有这种写法。

饿汉式

代码语言:javascript
复制
public class Singleton {

    private final static Singleton INSTANCE = new Singleton();

    private Singleton(){}

    public static Singleton getInstance(){
        return INSTANCE;
    }
}

在单例对象声明的时候就直接初始化对象,可以避免多线程问题,但是如果对象初始化比较复杂,会导致程序初始化缓慢。并且初始化后如果没有使用到的话,也会造成资源的浪费。

静态内部类

代码语言:javascript
复制
public class Singleton {

    private Singleton() {}

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。 不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了 线程的安全性,在类进行初始化时,别的线程是无法进入的。 优点:避免了线程不安全,延迟加载,效率高。^2

注意事项

1.如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。 2.如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。^1

对第一个问题修复的办法是:

代码语言:javascript
复制
private static Class getClass(String classname) throws ClassNotFoundException {     
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();  
      if(classLoader == null)     
         classLoader = Singleton.class.getClassLoader();     
      return (classLoader.loadClass(classname));     
   }     
}  

对第二个问题修复的办法是:

代码语言:javascript
复制
public class Singleton implements java.io.Serializable {     
   public static Singleton INSTANCE = new Singleton();     
      
   protected Singleton() {     
        
   }     
   private Object readResolve() {     
            return INSTANCE;     
      }    
}   

单例模式的优缺点

优点: 1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例 2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。 3.提供了对唯一实例的受控访问。 4.由于在系统内存中只存在一个对象,因此可以节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。 5.允许可变数目的实例。 6.避免对共享资源的多重占用。 ^3

缺点: 1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。 2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。 3.单例类的职责过重,在一定程度上违背了“单一职责原则”。 4.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。 ^3

推荐资料

Singleton is an angel but an evil!写的比较有深度,可以仔细看看。


标题:设计模式学习笔记之单例模式 作者:海加尔金鹰 地址:https://www.hjljy.cn/articles/2019/06/19/1560934965710.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 什么是单例模式
  • 单例模式的实现
    • 枚举
      • 饿汉式
        • 静态内部类
          • 注意事项
          • 单例模式的优缺点
            • 推荐资料
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档