设计模式总结 —— 单例设计模式

一、定义

      确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

二。使用场景

      当对象需要消耗的资源过多(如访问Io、数据库等),避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。

三、实现方法

(1)饿汉单例模式

      依靠静态对象的初始化实现单例

public class Singleton{
    private static Singleton mInstance = new Singleton();
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance(){
        return mInstance;
    }
}
复制代码
(2)懒汉单例模式

      第一次调用getInstance()后,单例对象就会被实例化。但每次调用getInstance()方法时都需要进行同步,会造成不必要的消耗。
      对于不频繁调用getInstance()的情况下,可以适用。

public class Singleton{
    private static Singleton mInstance;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance(){
        if( mInstance == null){
            mInstance = new Singleton();
        }
        return mInstance;
    }
}
复制代码
(3) Double Check Lock(DCL) 实现单例
public class Singleton{
    private volatile static Singleton mInstance;
    
    private Singleton() {}
    
    public static Singleton getInstance(){
        if( mInstance == null){
            synchronized(Singleton.class){
                if( mInstance == null){
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}
复制代码

      进行两次判空,第一次判断主要避免不必要的同步,第二次判断主要为了在同步情况下确认单例仍为空时,进行初始化。

volatile关键字的作用:
      1、防止重排序
      new对象时,会进行三件事件:
            (1)、给Singleton的实例分配内存;
            (2)、调用Singleton()的构造方法,初始化成员变量。
            (3)、将mInstance对象指向分配的内存空间。
而在JVM中(2)和(3)的顺序是无法被保证的,只能通过volalite保证其有序性。

      2、保证线程的可见性。

(4) 静态内部类单例模型

依靠静态内部类被使用时才被JVM加载的原理。

public class Singleton{
    private Singleton{}
    public static Singleton getInstance(){
        return SingletonHolder.mInstance;
    }
    
    //静态内部类
    private static class SingletonHolder{
        private static final Singleton mInstance = new Singleton();
    }
}
复制代码

静态内部类和非静态内部类加载时机的区别:

      非静态内部类,一定需要外部类实例化后才会被加载。

      静态内部类的加载不需要依附外部类,在使用时才加载进。

(5) 使用容器实现单例。

将多种单例类型注入到一个统一的管理类中,使用时根据key获取对应的单例对象。

public class SingletonManager{
    private static Map<String,Object> objMap = new HashMap<String,Object>();
    private SingletonManager{}
    
    public static void registerService(String key,Object instance){
        if(!object.containsKey(key)){
            objMap.put(key,instance);
        }
    }
    
    public static Object getService(String key){
        return objMap.get(key);
    }
}
复制代码
(6) 枚举单例

枚举类型可以定义自己的方法和自己的变量,而且枚举实例的创建是线程安全的,并且任何情况下都是单例。

public enum SingletonEnum{
    INSTANCE;
    public void doSomething(){
        System.out.println("do ");
    }
}
复制代码

转载于:https://juejin.im/post/5cba8f8a6fb9a068973eda56

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值