揭秘设计模式之单例模式

Posted 醉酒的小男人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了揭秘设计模式之单例模式相关的知识,希望对你有一定的参考价值。

什么是单例模式

单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。属于创建型模式。单例就是一个类只能有一个对象,单例模式在生活里也比较普遍,比如:像打印机、处理器(单核)、皇帝、太子、月亮、太阳等等,它们都是稀有资源,只能有一个实例对象。

代码案例

饿汉式

package singleton;
public class HungrySingleton {
    //先静态、后动态
    //先属性、后方法
    //先上后下
    private static final HungrySingleton INSTANCE = new HungrySingleton();

    //构造方法私有化
    private HungrySingleton(){}

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

懒汉式

package singleton;
public class LazySimpleSingleton {

    private LazySimpleSingleton(){}
    
    private static LazySimpleSingleton lazySimpleSingleton;
    
    public synchronized static LazySimpleSingleton getInstance(){
        if(lazySimpleSingleton == null){
            lazySimpleSingleton = new LazySimpleSingleton();
        }
        return lazySimpleSingleton;
    }
}

双重检查锁

package singleton;
/**
 * 双重检查锁
 */
public class LazyDoubleCheckSingleton {
    private LazyDoubleCheckSingleton(){}

    //volatile禁止指令重排序通过内存屏障
    private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton;

    public static LazyDoubleCheckSingleton getInstance(){
        if(lazyDoubleCheckSingleton == null){
            synchronized (LazyDoubleCheckSingleton.class){
                if(lazyDoubleCheckSingleton == null){
                    lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                    //1.分配内存给这个对象
                    //2.初始化对象
                    //3.设置lazy指向刚分配的内存地址
                }
            }
        }
        return lazyDoubleCheckSingleton;
    }
}

静态内部类

package singleton;
public class LazyInnerClassSingleton {
    private LazyInnerClassSingleton(){}

    public static final LazyInnerClassSingleton getInstance(){
        if(LazyHolder.LAZY != null){
           throw new RuntimeException("不许去创建多个实例");
        }
       return LazyHolder.LAZY;
    }

    //默认不加载
    private static class LazyHolder{
        private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
    }
}

枚举式

package singleton;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
 * 枚举式单例
 */
public enum  EnumSingleton {
    INSTANCE;
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) {
        try {
            EnumSingleton instance1 = null;
            EnumSingleton instance2 = EnumSingleton.getInstance();
            instance2.setData(new Object());

            FileOutputStream fos = new FileOutputStream("EnumSingleton.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(instance2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("EnumSingleton.obj");
            ObjectInputStream ois = new ObjectInputStream(fis);
            instance1 = (EnumSingleton)ois.readObject();
            ois.close();

            System.out.println(instance1.getData());
            System.out.println(instance2.getData());
            System.out.println(instance1.getData()==instance2.getData());

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

容器式

package singleton;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 类似于spring中的容器也是使用的Map
 */
public class ContainerSingleton {
    private ContainerSingleton(){}
    private static Map<String,Object> ioc = new ConcurrentHashMap<>();

    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 (Exception e){
                 e.printStackTrace();
              }
              return obj;
           }else{
               return ioc.get(className);
           }
       }
    }
}

序列化

package singleton;
import java.io.*;
/**
 * 反序列化导致破坏单例模式
 */
public class SeriableSingleton implements Serializable {

    private SeriableSingleton(){}

    public static final SeriableSingleton INSTANCE = new SeriableSingleton();

    /**
     * 当JVM从内存中反序列化地"组装"一个新对象时,就会自动调用这个
     * readResolve方法来返回我们指定好的对象了,单例规则也就得到了保证.
     * @return
     */
    public static SeriableSingleton getInstance(){
        return INSTANCE;
    }

   private Object readResolve(){
      return INSTANCE;
   }

    /**
     * 1.序列化就是把内存中的状态通过转换成字节码的形式,
     * 从而转换成一个I/O流,写入其它地方比如磁盘、网络等,内存中的状态会永久保存下来。
     * 2.反序列化就是将已经持久化的字节码内容转换成I/O流,通过I/O流的读取,
     * 把读取的内容转换成java对象,在转换过程中会重新创建对象new.
     * @param args
     */
    public static void main(String[] args) {
        SeriableSingleton s1 = null;
        SeriableSingleton s2 =SeriableSingleton.getInstance();

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("SeriableSingleton.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(s2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("SeriableSingleton.obj");
            ObjectInputStream ois = new ObjectInputStream(fis);
            s1 = (SeriableSingleton)ois.readObject();
            ois.close();

            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s1==s2);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

本地线程

package singleton;

public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance = new ThreadLocal<ThreadLocalSingleton>(){
        @Override
        protected ThreadLocalSingleton initialValue() {
            return super.initialValue();
        }
    };
    private ThreadLocalSingleton(){}

    public static ThreadLocalSingleton getInstance(){
        return threadLocalInstance.get();
    }

    public static void main(String[] args) {
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
    }
}

以上是关于揭秘设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之单例模式

设计模式之单例模式

Java设计模式之单例模式

设计模式之单例模式以及简单代码实现

设计模式之单例设计模式

设计模式之单例模式