单例模式总结 饿汉式 懒汉式 静态内部类 枚举 反射破坏单例 序列化 附代码

饿汉式 懒汉式单例模式参考博客 单例模式 饿汉式和懒汉式

静态内部类实现单例模式参考博客 静态内部类 单例设计模式举例

不管是饿汉式,还是懒汉式中的线程安全的双重检测机制和静态内部类实现单例模式,都会被反射破坏单例模式。利用反射得到私有构造方法,还是可以生成多个具体类,使用序列化使得单例模式失效代码如下

package 设计模式.单例模式.单例设计模式改进;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Created by Administrator on 2017/11/22 0022.
 * 单例设计模式:
 1构造方法私有化
 2声明一个本类对象
 3给外部提供一个静态方法获取对象实例
 饿汉式:在类被加载后,对象被创建,到程序结束后释放
 懒汉式: 在第一次调用getInstance方法时,对象被创建,到程序结束后释放

在项目中为什么使用单例,单例有什么好处?
        1.在设计工具类时(通常工具类只有功能方法,没有属性)
        2.工具类可能会被频繁调用
        3.为了节省重复创建对象所带来的内存消耗,从而提高效率
        能不能使用构造方法私有化+静态方法来替代单例呢????
        还是普通方法,会进栈,内存中只有一个对象长久占着,从节省内存角度考虑


        */
//使用构造方法私有化+静态方法来实现工具类
//方法在静态方法区就存在,类加载后就存在,调用很方便,但是方法一直

//用synchronized改进,解决多线程访问问题
//加上volatile关键字,保证变量的一致性,提醒编译器,他后面所定义的变量随时都有可能改变
//防止反射私有化实例方法
//让单例类可以被序列化

class Tools{
    private Tools(){};
    public static void print1(){

    }

}

public class Solution {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Singleton3 instance = Singleton3.getInstance();
        //Singleton1 s = new Singleton1();
        Singleton1 s = Singleton1.getInstance();
        s.print();
        Singleton1 s1 = Singleton1.getInstance();
        s1.print();
        System.out.println(s == s1);
        //用反射构建
        Constructor<Singleton1> con = Singleton1.class.getDeclaredConstructor();
        con.setAccessible(true);
        Singleton1 singleton1 = con.newInstance();
        Singleton1 singleton2 = con.newInstance();
        System.out.println("这两个对象是否一样?" + singleton1.equals(singleton2));

        //序列化破坏单例模式
        Singleton1 s2 =(Singleton1) Util.deepClone(s1);
        System.out.println("序列化的对象是否一样" + s2.equals(s1));

    }

}

//饿汉式:占用内存时间长,提高效率
class Singleton1 implements Serializable{
    private Singleton1(){}
    private static Singleton1 s = new Singleton1();
    public static Singleton1 getInstance(){
        return s;
    }
    public void print(){
        System.out.println("测试方法");
    }
}

//懒汉式:占用内存的时间短,效率低(懒加载,延迟加载)
//在多线程访问时会有安全问题
class Singleton2 implements Serializable{
    private Singleton2(){
        if (s != null){
            throw new RuntimeException("此类对象为单例模式,已经被实例化了");
        }
    }
    private volatile static Singleton2 s;
    public static Singleton2 getInstance() {
        if (s == null) {
            synchronized (Singleton2.class) {
                if (s == null) {
                    s = new Singleton2();
                }
            }
        }
        return s;
    }
    public void print(){
        System.out.println("测试方法");
    }
}

//静态内部类
class Singleton3 implements Serializable{

    private static class lazyLoader{
        static {
            System.out.println("加载了静态内部类");
        }
        private static final Singleton3 s = new Singleton3();
    }
    private Singleton3(){
        System.out.println("构造函数");
    }
    static {
        System.out.println("先加载谁");
    }
    public static Singleton3 getInstance(){
        System.out.println("getInstance方法");
        return lazyLoader.s;
    }

}

class Util {
    //序列化方式深拷贝SingleTon1
    public static Object deepClone(Singleton1 singleton1) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(singleton1);
            oos.close();
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            Object newInstance = ois.readObject();
            ois.close();
            return newInstance;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}


枚举实现单例模式

package com.company.反射与内省.单例设计模式枚举实现;

/**
 * Created by jason on 2018/1/6.
 */
public enum danli {
    INSTANCE;
    private String string;
    public String getString() {
        return string;
    }
    public void setString(String string) {
        this.string = string;
    }
    public void test(){
        System.out.println("测试开始");
    }
}

下面注释处运行会出错

package com.company.反射与内省.单例设计模式枚举实现;

import java.lang.reflect.Constructor;

/**
 * Created by jason on 2018/1/6.
 */
public class EnumSingleton {
    public static void main(String[] args) {
        danli one = danli.INSTANCE;
        danli two = danli.INSTANCE;
        System.out.println(one.getString());
        one.test();
        one.setString("wo shi one");
        System.out.println(one.equals(two));
        System.out.println(two.getString());

        try {
//            Constructor<danli> con = danli.class.getDeclaredConstructor();
//            con.setAccessible(true);
//            danli a = con.newInstance();
//            danli b = con.newInstance();
//            System.out.println(a == b);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

猜你喜欢

转载自blog.csdn.net/qq_31617121/article/details/80802020