了解Spring中常见的设计模式-------------------单例模式

  单例模式

优点:内存中只有一个实例,减少内存开销;可以避免对资源的多重占用;设置全局访问点,严格控制访问

缺点:没有接口难以扩展,如需要扩展只有修改代码

设计重点:

1、私有化构造器

2、延迟加载

3、保证线程安全

4、防止序列化与反序列化攻击

5、防止反射攻击

饿汉式单例

在单例类首次被加载的时候就创建实例,重写readResolve()方法可以防止序列化与反序列化的攻击,无法防止反射攻击,只有在构造函数中进行对象非空判断, 缺点:浪费内存空间

public class HungerSingleton {

    private static final HungerSingleton hungerSingleton = new HungerSingleton();

    private HungerSingleton() {
    }

    public HungerSingleton getInstance() {
        return hungerSingleton;
    }

    public Object readResolve() {
        return hungerSingleton;
    }
}


public class HungerStaticSingleton {

    private static final HungerStaticSingleton HUNGER_STATIC_SINGLETON;

    static {
        HUNGER_STATIC_SINGLETON = new HungerStaticSingleton();
    }

    private HungerStaticSingleton() {
    }

    public HungerStaticSingleton getInstance() {
        return HUNGER_STATIC_SINGLETON;
    }

}


public class SerializableHungerSingletonTest {
    public static void main(String[] args) {
        HungerSingleton hungerSingleton1 = null;
        HungerSingleton hungerSingleton2 = HungerSingleton.getInstance();

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("HungerSingleton.obj");
            ObjectOutputStream outputStream = new ObjectOutputStream(fos);
            outputStream.writeObject(hungerSingleton2);
            outputStream.flush();
            outputStream.close();

            FileInputStream fileInputStream = new FileInputStream("HungerSingleton.obj");
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            hungerSingleton1 = (HungerSingleton) objectInputStream.readObject();
            System.out.println(hungerSingleton1);
            System.out.println(hungerSingleton2);
            System.out.println(hungerSingleton1==hungerSingleton2);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}


测试结果:
com.tealala.pattern.singleton.hungerSingleton.HungerSingleton@36baf30c
com.tealala.pattern.singleton.hungerSingleton.HungerSingleton@36baf30c
true

懒汉式单例

该单例类只有被调用的时候才创建实例

public class LazySingleton {

    private static LazySingleton LAZY_SINGLETON;

    private LazySingleton() {
    }

    public synchronized static LazySingleton getInstance() {
        if (LAZY_SINGLETON == null) {
            LAZY_SINGLETON = new LazySingleton();
        }
        return LAZY_SINGLETON;
    }

}


public class LazySingletonDoubleCheck {

    private volatile static LazySingletonDoubleCheck lazySingletonDoubleCheck;

    private LazySingletonDoubleCheck() {
    }

    /**
     * cpu在执行时会转换成JVM指令执行
     * 指令重排序问题,volatile
     * 1、分配内存给对象
     * 2、初始化对象
     * 3、将初始化好的对象与内存建立连接,赋值
     * 4、用户初次访问
     * @return
     */
    public synchronized static LazySingletonDoubleCheck getInstance() {
        if (lazySingletonDoubleCheck == null) {
            synchronized (LazySingletonDoubleCheck.class) {
                if (lazySingletonDoubleCheck == null) {
                    lazySingletonDoubleCheck = new LazySingletonDoubleCheck();
                }
            }
        }
        return lazySingletonDoubleCheck;
    }
}


public class LazySingletonInnerClass {
    private LazySingletonInnerClass() {
        if(InnerLazySingleton.lazySingletonInnerClass!=null){
            throw new RuntimeException("不允许构建多个实例!!");
        }
    }

    public static final LazySingletonInnerClass getInstance() {
        return InnerLazySingleton.lazySingletonInnerClass;
    }

    /**
     * 利用JVM底层的逻辑,避免了线程安全的问题
     */
    private static class InnerLazySingleton {
        private static final LazySingletonInnerClass lazySingletonInnerClass = new LazySingletonInnerClass();
    }
}




public class LazySingletonTest {
    public static void main(String[] args) {
        LazySingleton lazySingleton = LazySingleton.getInstance();
        LazySingleton lazySingleton2 = LazySingleton.getInstance();
        System.out.println(lazySingleton.toString());
        System.out.println(lazySingleton2.toString());

        LazySingletonDoubleCheck lazySingletonDoubleCheck = LazySingletonDoubleCheck.getInstance();
        LazySingletonDoubleCheck lazySingletonDoubleCheck2 = LazySingletonDoubleCheck.getInstance();
        System.out.println(lazySingletonDoubleCheck.toString());
        System.out.println(lazySingletonDoubleCheck2.toString());

        LazySingletonInnerClass lazySingletonInnerClass = LazySingletonInnerClass.getInstance();
        LazySingletonInnerClass lazySingletonInnerClass2 = LazySingletonInnerClass.getInstance();
        System.out.println(lazySingletonInnerClass.toString());
        System.out.println(lazySingletonInnerClass2.toString());

    }
}


执行结果:
com.tealala.pattern.singleton.lazySingleton.LazySingleton@76ed5528
com.tealala.pattern.singleton.lazySingleton.LazySingleton@76ed5528
com.tealala.pattern.singleton.lazySingleton.LazySingletonDoubleCheck@2c7b84de
com.tealala.pattern.singleton.lazySingleton.LazySingletonDoubleCheck@2c7b84de
com.tealala.pattern.singleton.lazySingleton.LazySingletonInnerClass@3fee733d
com.tealala.pattern.singleton.lazySingleton.LazySingletonInnerClass@3fee733d

注册式单例

将每一个实例都缓存到统一的容器中,使用唯一标识获取实例,(枚举类可以防止反射攻击和序列化与反序列化攻击)

public enum LazySingleRegister {

    INSTANCE;

    private Object Data;

    public Object getData() {
        return Data;
    }

    public void setData(Object data) {
        Data = data;
    }

    public static LazySingleRegister getInstance() {
        return INSTANCE;
    }
}


public class LazySingleContainer {

    private LazySingleContainer() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<String, Object>();

    public static Object getBean(String className) {

        synchronized (ioc) {
            if (!ioc.containsKey(className)) {
                Object obj = null;
                try {
                    obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                return obj;
            }
            return ioc.get(className);

        }
    }
}



public class ThreadLocalSingleton {

    private ThreadLocalSingleton() {
    }

    private static final ThreadLocal<ThreadLocalSingleton> THREAD_LOCAL = new ThreadLocal<ThreadLocalSingleton>() {
        @Override
        protected ThreadLocalSingleton initialValue() {
            return new ThreadLocalSingleton();
        }
    };

    public static ThreadLocalSingleton getInstance() {
        return THREAD_LOCAL.get();
    }
}
发布了35 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tealala/article/details/103454525