- 普通的类
public class Controller {
public Controller() { }
public void func(){
System.out.println("1");
}
}
- 我想把它变成单例的(用一个枚举类持有想要实现单例的普通类)
public enum ControllerHolder {
INSTANCE;
private Controller controller;
ControllerHolder() {
this.controller = new Controller();
}
public static Controller getInstance(){
return ControllerHolder.INSTANCE.controller;
}
}
- 测试下
public static void main(String[] args) {
System.out.println(ControllerHolder.getInstance());
System.out.println(ControllerHolder.getInstance());
System.out.println(ControllerHolder.getInstance());
System.out.println(ControllerHolder.getInstance());
System.out.println(ControllerHolder.getInstance());
}
输出:
com.iluwatar.singleton.Controller@6e8cf4c6
com.iluwatar.singleton.Controller@6e8cf4c6
com.iluwatar.singleton.Controller@6e8cf4c6
com.iluwatar.singleton.Controller@6e8cf4c6
com.iluwatar.singleton.Controller@6e8cf4c6
- 现在看起来是单例的,但是对多线程支持么?反编译看下
- 在源代码目录下,执行
javac ./*.java
将包下的文件全部编译
- 用java 自带的javap反编译看看
javap .\ControllerHolder.class
- javap 反编译的不太好,看不出具体情况, 还是使用jad 来反编译看看吧
- 执行
.\jad.exe D:\workspace_idea_try\java-design-patterns\singleton\src\main\java\com\zzk\singleton\ControllerHolder.class
会在jad.exe同级目录生成一个ControllerHolder.jad文件.内容如下↓↓↓
public final class ControllerHolder extends Enum
{
public static ControllerHolder[] values()
{
return (ControllerHolder[])$VALUES.clone();
}
public static ControllerHolder valueOf(String s)
{
return (ControllerHolder)Enum.valueOf(com/zzk/singleton/ControllerHolder, s);
}
private ControllerHolder(String s, int i)
{
super(s, i);
controller = new Controller();
}
public static Controller getInstance()
{
return INSTANCE.controller;
}
public static final ControllerHolder INSTANCE;
private Controller controller;
private static final ControllerHolder $VALUES[];
static
{
INSTANCE = new ControllerHolder("INSTANCE", 0);
$VALUES = (new ControllerHolder[] {
INSTANCE
});
}
}
public final class ControllerHolder extends Enum
这一行说明 枚举就是一个普通的类,只是继承了Enum类.
public static final ControllerHolder INSTANCE;
这一行, ControllerHolder是静态的,并且INSTANCE = new ControllerHolder("INSTANCE", 0);
在静态代码块中执行, 这种方式 jvm会保证运行static代码块是线程安全并且只执行一次的,所以Controller作为ControllerHolder的一个属性,自然也只声明一次和线程安全的
- 这种枚举单例的实现并没有延迟加载的优点, 一上来不管用没用到,都在静态方法中初始化了.
- 上面写的,将Controller和ControllerHolder分开写了,这种方式一般不采用,因为如果有人直接new了一个Controller,会导致该Controller不是单例了,因此通常的写法是将枚举写成内部枚举类,代码如下↓↓↓
public class SingletonExample7 {
private SingletonExample7() {}
public static SingletonExample7 getInstance() {
return Singleton.INSTANCE.getInstance();
}
private enum Singleton {
INSTANCE;
private SingletonExample7 singleton;
Singleton() {
singleton = new SingletonExample7();
}
public SingletonExample7 getInstance() {
return singleton;
}
}
}