设计模式02-单例模式

介绍


单例模式可以说是最简单的创建型模式了,面试的时候大部分会以此作为面试题。但相对来说,它挺复杂的,针对于不同情形,有不一样的实现方式。如经典的线程不安全懒汉式,线程安全懒汉式,饿汉式,双检锁/双重校验锁,静态内部类,枚举

定义


在某些场合,出于节约资源等原因,需要只保证一个类只有一个实例化对象。如线程池,数据库连接,缓存,日志对象,打印机等等

优点

  1. 节省资源,减少内存开销,不用频繁的创建和销毁实例
  2. 避免对资源的多重占用

缺点

  1. 没有接口,不能继承。因为构造器是私有的,不能被实例化。
  2. 与单一职责原则冲突。正常一个类只需要关心自己的内部逻辑(一项职责),不需要关心外部如何实例化它(又一项职责)

核心思想

  1. 限制构造器的访问范围,设置为private
  2. 只能通过一个静态方法来返回实例,且实例为静态的

单例模式的实现方式


线程不安全懒汉式

该模式支持Lazy instantiaze(延迟实例化),但该方式线程不安全,不支持多线程

public class Singleton{
    private static Singleton singleton;

    private Singleton(){}

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

线程安全懒汉式

该模式支持Lazy instantiaze(延迟实例化),且该方式线程安全,支持多线程,与线程不安全的唯一区别是获取实例方法加锁,添加上了synchronized关键字

public class Singleton{
    private static Singleton singleton;

    private Singleton(){}

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

缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率,因为加锁代表访问该方法需要同步,必定会产生相对的堵塞。而且我们只需要在第一次执行该方法的时候需要同步,因为第二次的话,该实例对象将不会是null。

应用场景:

  1. getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。

饿汉式
该模式不支持Lazy instantiaze(延迟实例化),但该方式线程安全,支持多线程。

public class Singleton {  
    private static Singleton instance = new Singleton();  

    private Singleton (){}  

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

优点:由于classloder(类加载器)的原因,避免了多线程的同步问题,没有加锁,效率会提高

缺点: 没有延迟实例化机制,在类加载的时候就初始化,浪费内存

应用场景:
这是最常用的单例模式实例方式,但是容易产生垃圾对象。这是一种急切实例化的方式,不再是延迟实例化。

双检锁/双重校验锁(DCL,即 double-checked locking)

该模式支持Lazy instantiaze(延迟实例化),但该方式线程安全,支持多线程,且能保持高性能。

为什么叫双重检查?因为在检查实例化对象是否为null后,进入了同步代码块,然后在代码块中又进行了一次检查。

与线程安全懒汉式不同点:

  1. 实例化变量被设置为volatile
  2. 不再是同步方法,而是在进行第一次校验之后,进入同步代码块,锁定实例化类
  3. 在同步代码块中还要进行第二次校验才能被实例化
public class Singleton {  
    private volatile static Singleton singleton;

    private Singleton(){}

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

静态内部类单例模式

该模式支持Lazy instantiaze(延迟实例化),且该方式线程安全,支持多线程,且能保持高性能。

其核心是静态内部类,静态保证了线程安全,内部类保证了懒加载

public class Singleton{
    private Singleton{}
    private static class SingletonHolder{
        private static Singleton instance =new Singleton();
    }
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

枚举单例模式

该模式支持延迟加载,且线程安全,容易理解

它定义一个枚举的元素,它就代表了Singleton的一个实例,是最简单的单例

public enum Singleton{
    uniqueInstance;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值