小学生学习设计模式之单例模式

2020/4/7 17:02:02

本文主要是介绍小学生学习设计模式之单例模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

小学生学习设计模式之单例模式

一、什么是单例模式

单例模式(Singleton Pattern),涉及一个单一的类,该类负责创建自己的对象,确保只有单个对象创建,提供一种访问其唯一的对象的方式,可以直接访问,不需要实例该类的对象。

  • 单例类只有一个实例,外部不能实例单例类,构造方法隐藏
  • 单例类必须自己创建自己的唯一实例
  • 单例类必须提供这一实例

二、实现

image-20200405175034864
SingletonPatterm
public class Singleton {

    /**
     * 唯一实例
     */
    private static Singleton instance = new Singleton();

    /**
     * 构造方法隐藏,无法实例
     */
    private Singleton(){}

    /**
     * 提供外部访问唯一实例的方法
     * @return
     */
    public static Singleton getInstance(){
        return instance;
    }

    public void message(){
        System.out.println("This is Singleton Patterm");
    }
}
复制代码
public class SingletonPattermDemo {
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        Singleton singleton = Singleton.getInstance();
        System.out.println(singleton == instance);
        instance.message();
    }
}
/*
* true
* This is Singleton Patterm
*/
复制代码

三、单例模式的几种实现方法

image-20200405175034864
几种实现方式

1. 懒汉式,线程不安全

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance(){
        return instance = instance != null?instance:new Singleton();
    }
}
复制代码

2. 懒汉式,线程安全

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        return instance = instance != null?instance:new Singleton();
    }
}
复制代码

3. 饿汉式

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}
复制代码

4. 双检锁/双重校验锁(DCL,double-checked locking)

public class Singleton {
    private volatile static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
复制代码

5. 静态内部类

public class Singleton {
    private static class SingletonInstance{
        private static final Singleton instance = new Singleton();
    }
    private Singleton(){}
    public static final Singleton getInstance(){
        return SingletonInstance.instance;
    }
}
复制代码

6. 登记式

public class Singleton implements Serializable{
    private static Map<String,Object> map;
    
    static{
        map = new ConcurrentHashMap<>();
        map.put(Singleton.class.getName(),new Singleton());
    }
    private Singleton(){
        System.out.println(Singleton.class.getName());
    }

    public static final Object getInstance(String name){
        if (name == null){
            name = Singleton.class.getName();
        }
        if(map.get(name) == null){
            try {
                map.put(name,Class.forName(name).newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
}
复制代码

7. 枚举(推荐)

public enum Singleton{
    INSTANCE;
}
复制代码

四、破解单例模式

1. 通过反射破解单例(枚举除外)

public class SingletonPattermDemo {
    public static void main(String[] args)  throws Exception{
     
        Class cla = Class.forName("cn.pzaily.Singleton");
        Constructor constructor = cla.getDeclaredConstructor(null);
        constructor.setAccessible(true);

        Singleton singleton1 = (Singleton) constructor.newInstance();
        Singleton singleton2 = (Singleton) constructor.newInstance();
        System.out.println(singleton1 == singleton2);
    }
}
复制代码

解决办法:

public class Singleton {
    private static final Singleton instance = new Singleton();
    private Singleton(){
        //在构造器中加个逻辑判断,多次调用抛出异常
        if(instance != null){
            throw new RuntimeException();
        }
    }
    public static final Singleton getInstance(){
        return instance;
    }
}
复制代码

2. 通过反序列化机制破解单例(枚举除外)

public class SingletonPattermDemo {
    public static void main(String[] args) throws Exception {
        String path = "xxx";
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        Singleton instance3 = null;

        try(FileOutputStream fileOutputStream = new FileOutputStream(path);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            FileInputStream fileInputStream = new FileInputStream(path);
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            ){
            objectOutputStream.writeObject(instance1);
            instance3 = (Singleton) objectInputStream.readObject();
        }catch (Exception e){
            e.printStackTrace();
        }
        
        System.out.println(instance1 == instance3);
        System.out.println(instance1 == instance2);
    }
}
复制代码

解决办法

public class Singleton implements Serializable{
    private static final Singleton instance = new Singleton();
    private Singleton(){
        if(instance != null){
            throw new RuntimeException();
        }
    }
    public static final Singleton getInstance(){
        return instance;
    }
    //反序列化定义该方法,则不需要创建新对象
    private Object readResolve() throws ObjectStreamException{
        return instance;
    }
}
复制代码

本文使用 mdnice 排版



这篇关于小学生学习设计模式之单例模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程