Talk is cheap Show me the code
个人学习笔记--仅供参考
注册式单例
注册式单例又称为登记式单例,就是将每一个实例都登记到某一个地方,使用唯一的标
识获取实例
注册式单例有两种写法:一种为容器缓存,一种为枚举登记
枚举
package pattern;
/**
* 注册式单例又称为登记式单例,就是将每一个实例都登记到某一个地方,使用唯一的标
识获取实例。注册式单例有两种写法:一种为容器缓存,一种为枚举登记。先来看枚举
式单例的写法,来看代码
* @author qsnp236
*
*/
public enum EnumSingleton{
// 饿汉
HUNGARY("hungary"),
// 懒汉
LAZY("lazy"),
// 内部类
INNERCLASS("inner_class");
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
EnumSingleton(String name){
this.name=name;
}
public static EnumSingleton getInstance(String desc) {
for (EnumSingleton configType : EnumSingleton.values()){
if (configType.getName().equals(desc)){
return configType;
}
}
throw new IllegalArgumentException("无法转化为对应的enum类型,原因是未知描述信息: " + desc);
}
}
测试类
package pattern;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class EnumSingletonTest {
public static void main(String[] args) {
EnumSingleton s1=EnumSingleton.getInstance("lazy");
FileOutputStream fos;
try {
fos = new FileOutputStream("EnumSingleton.obj");
ObjectOutputStream os= new ObjectOutputStream(fos);
os.writeObject(s1);
os.flush();
os.close();
FileInputStream fis= new FileInputStream("EnumSingleton.obj");
ObjectInputStream ois= new ObjectInputStream(fis);
EnumSingleton s2=(EnumSingleton) ois.readObject();
ois.close();
System.out.println(s1);
System.out.println(s2);
System.out.println(s1.getName());
System.out.println(s2.getName());
System.out.println(s1==s2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试结果
LAZY
LAZY
lazy
lazy
true
底层代码
static
{
INSTANCE = new EnumSingleton("INSTANCE", 0);
$VALUES = (new EnumSingleton[] {
INSTANCE
});
}
原来,枚举式单例在静态代码块中就给INSTANCE 进行了赋值,是饿汉式单例的实现,
序列化和反序列化中,我们发现枚举类型其实通过类名和Class 对象类找到一个唯一的枚举对象。因此,枚举对
象不可能被类加载器加载多次,反射中,在newInstance()方法中做了强制性的判断,如果修饰符是Modifier.ENUM 枚举类型,
直接抛出异常
接下来看注册式单例还有另一种写法,容器缓存的写法,创建ContainerSingleton 类
package pattern;
import java.io.Serializable;
import java.nio.file.SecureDirectoryStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 容器式写法适用于创建实例非常多的情况,便于管理。但是,是非线程安全的。比如spring IOC 容器
*
* @author qsnp236
*
*/
public class ContainerSingleton implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private ContainerSingleton() {
}
private static Map<String, Object> ioc = new ConcurrentHashMap<String, Object>();
public static Object getBean(String className) {
synchronized (ioc) {
if (!ioc.containsKey(className)) {
Object obj = null;
try {
Class<?> clazz = Class.forName(className);
obj = clazz.newInstance();
ioc.put(className, obj);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
} else {
return ioc.get(className);
}
}
}
}