每日java基础 - 单例模式

本文深入解析单例模式的定义、作用及其实现方式,包括单线程与多线程环境下的经典实现,如饿汉式与懒汉式单例。探讨其在资源管理中的应用,如线程池、缓存等,以及单例模式的优缺点和注意事项。

目录

一、单例模式的定义和理解

1、1单例模式及其单线程环境下的经典实现

1、介绍一下类图

2、单线程下单例模式的两种实现方式

1、2 多线程下的单例模式



一、单例模式的定义和理解

定义:某个类只有一个实例,并且提供一个全局访问点。(类  -- 一个实例 -- 一个全局访问点)

类型:创建型模式

理解

整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,显然,这种方式简化了在复杂环境下的配置管理。

  特别地,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。事实上,这些应用都或多或少具有资源管理器的功能。例如,每台计算机可以有若干个打印机,但只能有一个 Printer Spooler (单例) ,以避免两个打印作业同时输出到打印机中。再比如,每台计算机可以有若干通信端口,系统应当集中(单例) 管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态

  综上所述,单例模式就是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种方法。


使用场景:

当系统中只需要一个实例对象或者系统中只允许一个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使用单例模式。

  • 有状态的工具类对象;
  • 频繁访问数据库或文件的对象;

优缺点

  • 节约系统资源、提高了系统效率,同时也能够严格控制客户对它的访问。
  • 也许就是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,所以扩展起来有一定的困难。

单例模式的注意事项

  • 在使用单例模式时,我们必须使用单例类提供的公有工厂方法得到单例对象,而不应该使用反射来创建,否则将会实例化一个新对象。
  • 此外,在多线程环境下使用单例模式时,应特别注意线程安全问题。

1、1单例模式及其单线程环境下的经典实现

1、介绍一下类图

  • 类图三部分,依次是类名、属性、方法;
  • <<……>>中的信息为注释信息;
  • 修饰符
修饰符类图中的符号
private-
protected#
public+
包可见啥都没有
  • 带下划线的属性或方法代表是静态的。

 

单例模式的类图如下,这表明单例模式的类具有三个属性

  • 私有的构造方法;
  • 指向自己实例的私有静态引用(-Singleton singleton
  • 以自己实例为返回值的公有静态方法(+Singleton getInstance())(一个全局访问点)


2、单线程下单例模式的两种实现方式

理解概念:在 类加载 中的 立即加载  和 延迟加载

  • 立即加载:在类加载初始化的时候主动创建实例;(一开始就有危机意识)
  • 延迟加载:等到真正使用的时候才去创建实例,不用时不去主动创建。(火烧眉毛了才动)

基于这两种不同的理念,在单线程下,单利模式也就有两种相应的实现方式

  • 饿汉单例 (基于立即加载):在单例类被加载时候,就实例化一个对象,并将其交给自己的引用;
  • 懒汉单例 (基于延迟加载):只有在真正使用的时候才会实例化一个对象并交给自己的引用。

从速度和反应时间角度来讲,饿汉式(又称立即加载)要好一些;从资源利用效率上说,懒汉式(又称延迟加载)要好一些。


饿汉单利模式如下:

/ 饿汉单例(立即加载)
public class Singleton1 {

    // 指向自己实例的私有静态引用,主动创建
    private static Singleton1 singleton1 = new Singleton1();

    // 私有的构造方法
    private Singleton1(){}

    // 以自己实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton1 getSingleton1(){
        return singleton1;
    }
}

类加载的方式是按需加载,且加载一次。因此,在上述单例类被加载时,就会实例化一个对象并交给自己的引用,供系统使用;而且,由于这个类在整个生命周期中只会被加载一次,因此只会创建一个实例,即能够充分保证单例。


懒汉单例模式如下:

// 懒汉式单例
public class Singleton2 {

    // 指向自己实例的私有静态引用
    private static Singleton2 singleton2;

    // 私有构造方法
    private Singleton2(){}

    // 以自己实例为返回值的静态公有方法,静态工厂方法
    public static Singleton2 getSingleton2(){
        // 被动创建,在真正需要使用时才去创建
        if (singleton2 == null) {
            singleton2 = new Singleton2();
        }
        return singleton2;
    }
}

 

1、2 多线程下的单例模式

参考:彻头彻尾理解单例模式与多线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值