Design pattern ——singleton pattern(单例深入研究)

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);
			}

		}

	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值