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

设计模式-单例模式

作者头像
码哥字节
发布2021-07-27 10:46:27
3990
发布2021-07-27 10:46:27
举报
文章被收录于专栏:Java 技术栈

单例模式(Singleton)也叫单态模式,是设计模式中最为简单的一种模式,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,也因此有些设计大师并把把其称为设计模式之一。

使用场景

许多时候整个系统只需要拥有一个全局对象,这样有利于我们协调系统整体的行为。实际场景又哪些?如下

  1. Windows的Task Manager(任务管理器)就是很典型的单例模式。我们是不能打开两个 windows task manager。
  2. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
  3. 网站的计数器,通常采用单例模式实现,否则难以同步。
  4. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
  5. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
  6. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
  7. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
  8. 工具类对象。

总结一下:单例模式一般发生在一下情况:

(1)资源共享,避免由于资源操作导致的性能或者损耗。

(2)控制资源的情况下,资源见的相互通信。如线程池。

基本实现思路

单例模式要求类永远只返回一个对象引用和一个获得该实例的方法(必须是静态方法,通常使用 getInstance 这个名称)。网上又很多种写法,但是有的写法是有问题的这种我就不展示了,只记住正确的。

实现思路主要以下步骤:

  • 将该类的构造方法定义私有方法,这样其他地方就不能通过该类的构造方法来任意实例化该类的对象,只有通过该类提供的 getInstance 静态方法获取。
  • 提供一个静态方法,如果该类持有的引用不为空则返回这个引用,否则就创建该类的实例并将实例赋值给引用。

单例模式写法

  1. 饿汉式 (静态常量)【可用】

优点:写法简单,类加载的时候就完成实例化。避免了多线程实例化的同步问题。 缺点:在类加载的时候就实例化,没有达到 Lazy Loanding 的思想。假如至始至终没有使用这个实例们就会造成内存浪费。

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

    private final static Singleton INSTANCE = new Singleton();

    private Singleton(){}

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

2. 懒汉式(通过同步方法)【不推荐使用】

缺点:通过 synchronized 同步实现多线程的安全问题,但是效率太低了,每个线程获取实例的时候都要同步,只需要在初始化的时候同步即可,后面可以直接 return 而不需要同步。

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

    private static Singleton singleton;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

3. 双重检验(Double Check)【可使用】

volatile 修饰 singleton 变量,多线程初始化其他读线程立刻读取写后的数据。 优点:线程安全,也实现了延迟加载。同时效率也高,非空判断然后再同步,同步的代码块再判断非空创建。

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

    private static volatile Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

4. 静态内部类【可使用】

跟饿汉式一样通过类加载机制初始化保证只有一个线程保证安全。但是饿汉式没有实现懒加载。 静态内部类实现了懒加载,当Singleton加载时并不立即实例化 INSTANCE。而是在调用 getInstance() 方法才会 加载 SingletonHolder类从而完成 Singleton 的实例化。 优点:避免了线程安全问题,延迟加载,效率高。

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

    private Singleton() {}

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

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

5. 枚举 【可使用】

利用枚举特性,不仅避免多线程同步问题,还能防止序列化重新创建对象。实例就是我们的 INSTANCE INSTANCE.method();

代码语言:javascript
复制
public enum Singleton {
    INSTANCE;
    public void method() {

    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码哥字节 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用场景
  • 基本实现思路
  • 单例模式写法
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档