Singleton其实就是单例,即一个类在一个应用程序中只被实例化一次,只有一个对象。
本节讨论三种实现方式
- 私有构造+共有成员
 - 私有构造+静态工厂方法+私有成员
 - 枚举实现
 
文章目录
1、共有成员
构造方法私有,有一个该类类型的公有不可变的实例域。
1.1 code
public class Singleton01 {
    public static final Singleton01 singleton01 = new Singleton01();
    private Singleton01(){}
}
 
当类加载的时候就会创建静态域,同时构造函数私有,因此可以保证唯一实例。
客户端调用:
Singleton01 singleton01 = Singleton01.singleton01;
 
1.2 分析
-  
优点:实现简单;能够明确指导这是一个单例对象,因为公有的静态域时final的,只会存在一个。
 -  
缺点:可以利用反射调用私有构造方法而二次创建该对象
 
2、静态工厂方法
将成员定义为私有,提供一个静态方法,返回对象。同时构造方法私有
2.1 code
public class Singleton02 {
    /**
     * 私有
     */
    private static final Singleton02 instance = new Singleton02();
    private Singleton02(){}
    /**
     * 获取唯一的Singleton02实例
     * @return
     */
    public static Singleton02 getInstance(){
        return instance;
    }
}
 
对于静态方法getInstance的调用,返回的都是同一个Singleton02实例。
客户端调用:
Singleton02 instance = Singleton02.instance;
 
2.2 分析
-  
优点:(1)灵活,只需要改变
getInstance方法就能修改是否时单例(例如改为每个线程创建一个);(2)可以使用方法引用提供参数,写起来优雅;(3)可以编写范型Singleton工厂,30条在分析。 -  
缺点:和1相比,不明显是单例;没有解决反射破坏单例的问题。
 
注意:
上述两种方法,出了反射调用私有构造方法破坏单例外,反序列化也会破坏单例,针对反序列化的问题,可以声明实例域是瞬时的,并提供一个 readResolves,这点在第89条讨论。
private static final transient Singleton02 instance = new Singleton02();
 
3、使用枚举
将想要单例的类定义为一个枚举类型
3.1 code
public enum Singleton03 {
    INSTANCE("zhangsan","male");
    private String name;
    private String gender;
    Singleton03(String name, String gender) {
        this.name = name;
        this.gender = gender;
    }
}
 
客户端使用:
Singleton03 instance = Singleton03.INSTANCE;
 
3.2 分析
-  
优点:安全,枚举的内部实现就禁用了反射和反序列机制。
 -  
缺点:如果单例类必须扩展一个超类,这时候就不适用了。因为枚举不能继承其他类。
 





