单例模式

2018-06-26  本文已影响0人  昼暗
背景

系统中一个类只产生一个实例,好处

  1. 可以省略创建对象所花费的时间
  2. new操作减少, 因而系统内存的使用频率也会降低, 将减轻GC的压力
代码
  1. 缺点: 此时我们没有真正使用单例类, 但是单例类还是被创建了.所以我们希望可以延迟加载
public class Singleton {
    
    private Singleton(){
        System.out.println("Singleton is create");
    }
    
    private static Singleton instance = new Singleton();
    
    public static Singleton getInstance () {
        return instance;
    }
    
    public static void createString(){
        System.out.println("createString in Singleton");
    }

}
  1. 改进
    缺少: 可以实现延迟加载 但是使用了同步关键字会降低性能
public class LazySingleton {
    
    private LazySingleton(){
        System.out.println("LazySingleton is create");
    }
    
    private static LazySingleton instance = null;
    
    public static synchronized LazySingleton getInstance(){
        if(instance==null)
            instance = new LazySingleton();
        return instance;
    }
    
}
  1. 继续改进
    StaticSingleton加载时内部类不会被初始化
    当getInstance被调用时, 才会加载内部类,从而初始化instance,
    由于实例的建立实在类加载时完成,所以对多线程友好
public class StaticSingleton {
    
    private StaticSingleton() {
        System.out.println("StaticSingleton is create");
    }
    
    private static class SingletonHolder{
        private static StaticSingleton instance = new StaticSingleton();
    }
    
    public static StaticSingleton getInstance(){
        return SingletonHolder.instance;
    }
}
  1. 通常情况下, 以上基本可以确保系统中只存在唯一实例. 但仍有合法的方法, 可能导致系统中出现多个实例
public class SerSingleton implements Serializable{

    String name;
    
    private SerSingleton(){
        System.out.println("SerSingleton is create");
        name = "SerSingleton";
    }
    
    private static SerSingleton instance = new SerSingleton();
    
    public static SerSingleton getInstance (){
        return instance;
    }
    
    public static void createString(){
        System.out.println("createString in Singleton");
    }
    
    // 可以防止反序列化时 生成新的实例 
        // 方法注释掉的化, 会输出false
    private Object readResolve(){
        return instance;
    }
    
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SerSingleton s1 = null;
        
        //对象序列化
        SerSingleton s = SerSingleton.getInstance();
        FileOutputStream fos = new FileOutputStream("SerSingleton.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(s);
        oos.flush();
        oos.close();
        // 反序列化
        FileInputStream fis = new FileInputStream("SerSingleton.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        s1 = (SerSingleton)ois.readObject();
        
        System.out.println(s == s1);
        
    }
}
上一篇下一篇

猜你喜欢

热点阅读