spring 设计模式篇—单例模式

2018-08-10  本文已影响149人  Lucksheep

一、什么是单例模式?

    单例:一个类模版,在整个系统运行过程中,只允许产生一个事例(有且只有一个)。

二、保存单例的技术方案有哪些?

  1. 饿汉式:在实例使用之前,不管用不用,都先new出来,避免了线程安全问题;
/**
 * @ather: lucksheep
 * @date: 2018/8/6 19:46
 * @description: 饿汉式
 */
public class Hungry {

    private Hungry(){}

    //先静态、后动态
    //先属性、后方法
    //先上后下
    private static final Hungry hungry=new Hungry();

    public static Hungry getInstance(){
         return hungry;
    }
}

  1. 懒汉式:默认加载的时候不实例化,在需要用到的时候才实例化,延迟加载;
    第一种:
/**
 * @ather: lucksheep
 * @date: 2018/8/7 11:18
 * @description: 懒汉式
 */
public class LazyOne {

    private LazyOne(){}

    private static LazyOne lazy=null;

    public static LazyOne getInstance(){
        if(lazy==null){
            lazy=new LazyOne();
        }
        return lazy;
    }
}

第二种:

/**
 * @ather: lucksheep
 * @date: 2018/8/9 14:25
 * @description:
 */
public class LazyTwo {

    private LazyTwo(){}

    private static LazyTwo lazy=null;

    public static synchronized LazyTwo getInstance(){
        if(lazy==null){
            lazy=new LazyTwo();
        }
        return lazy;
    }
}

第三种:

/**
 * @ather: lucksheep
 * @date: 2018/8/9 14:25
 * @description:
 */
public class LazyThree {

    private static boolean initialized = false;

    //默认使用LazyThree的时候,先初始化内部类
    //如果没使用,内部类是不加载的
    private LazyThree(){

        //防止反射
        synchronized (LazyThree.class){
            if(initialized == false){
                initialized = !initialized;
            }else{
                throw new RuntimeException("单例已被侵犯,不给你看!");
            }
        }
    }

    public static final synchronized LazyThree getInstance(){
        return LazyHolder.lazy;
    }

    private static class LazyHolder{
        private static final LazyThree lazy=new LazyThree();
    }

}

  1. 注册登记式:每使用一次,都往一个固定的容器中去注册并且将使用过的对象进行缓存,下次去取对象的时候,就直接从缓存中取值,以保证每次获取的都是同一个对象;IOC中的单例模式就是典型的注册登记式单例

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ather: lucksheep
 * @date: 2018/8/10 15:48
 * @description: 注册登记式
 */
public class RegisterMaps {

    private static Map<String,Object> registerMaps=new HashMap<>();
    //如果要安全的 ConcurrentHashMap

    public static RegisterMaps getInstance(String name){
        if(null == name){
            name = RegisterMaps.class.getName();
        }
        if(registerMaps.get(name) == null){
            registerMaps.put(name,new RegisterMaps());
        }
        return (RegisterMaps) registerMaps.get(name);
    }
}
  1. 枚举式:这个很简单我就不说了。
/**
 * @ather: lucksheep
 * @date: 2018/8/10 15:57
 * @description: 枚举
 */
public enum  RegisterEnum {

    ONE,TWO,Three;

}
  1. 序列化与反序列化单例:如果要保证单例安全,只需要重写 private Object readResolve(){}这个方法。
/**
 * @ather:  lucksheep
 * @date: 2018/8/10 16:07
 * @description: 序列化单例
 */
public class Serializes implements Serializable {

    private static final long serialVersionUID = 3239595067725719650L;

    private Serializes(){}

    public final  static Serializes serializes=new Serializes();

    public static  Serializes getInstance(){
        return serializes;
    }

    /**
     * 加上可以保证单例是安全的
     * 原因:序列化与反序列化中的一个协议,为了实现实例化后,
     *       对象重复利用,它可以实现 readResolve() 这个方法,这个方法是JVM自动去调用的
     * @return
     */
    private Object readResolve(){
        return serializes;
    }
}
上一篇下一篇

猜你喜欢

热点阅读