单例模式(八种写法)

描述

单例模式是常见的一种设计模式,使用单例模式的好处是节省内存和计算、保证结果正确、方便管理,最常用的有饿汉式懒汉式两种,当然除了这两种还有另外几种方式,以下会详细介绍。
单例的实现思路为如下两步:

  1. 将该类的构造方法定义为私有方法,这样通过其它方法无法实例化该对象,只能通过该类提供的静态方法获取该类的唯一实例。
  2. 在该类提供一个静态方法,该方法持有该类的一个引用,当调用该方法时,如果引用不为空则直接返回,如果引用为空则创建实例并返回。

单例的使用场景:

  1. 无状态的工具类:比如日志工具类,不管是在哪里使用,我们需要的只是它帮我们记录日志信息,除此之外,并不需要在它的实例对象上存储任何状态,这时候我们就只需要一个实例对象即可。
  2. 全局信息类:比如我们在一个类上记录网站的访问次数,我们不希望有的访问被记录在对象A上,有的却记录在对象B上,这时候我们就让这个类成为单例。

单例模式的八种写法

1.饿汉式-静态常量 [可用]

class Singleton{
    private final static Singleton singleton = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return singleton;
    }
}

2.饿汉式-静态代码块 [可用]

class Singleton{
    private static Singleton singleton;
    static{
        singleton = new Singleton();
    }
    private Singleton(){}
    public static Singleton getInstance(){
        return singleton;
    }
}

3.懒汉式-非线程安全 [不可用]

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

4.懒汉式-线程安全 同步方法 [不推荐用]

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

5.懒汉式-线程不安全 同步代码块 [不可用]

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

6.双重检查机制 [推荐用]

为什么要用volatile
由于cpu与jvm多线程指令优化,会发生指令重排,volatile的特性就是可以保证多线程之间的可见性禁止指令重排
如果不加volatile多线程环境下会发生NPE

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;
    }
}

7.静态内部类 [推荐用]

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

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

8.枚举 [推荐用]

enum Singleton{
    INSTANCE;
    public void whateverMethod(){
        System.out.println("hello");
    }
}

方法对比

  1. 最好的方法是利用枚举,因为还可以防止反序列化重新创建新的对象
  2. 非线程同步的方法不能使用
  3. 如果程序一开始要加载的资源太多,那么就应该使用懒加载
  4. 饿汉式如果是对象的创建需要配置文件就不适用
  5. 懒加载虽然好,但是静态內部类这种方式会引入编程复杂性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值