单例模式,基于Java反射机制的实现

本文介绍了在Java开发中如何使用反射机制实现单例模式。详细讲解了单例模式的重要性,阐述了懒汉式的单例实现,并通过定义单例注解来标记类为单例。同时强调了单例类的构造方法要求。最后提供了测试代码以验证单例模式的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在实际开发中,单例模式是一种很有用的设计模式,能很好的解决我们只需要类的一个实例的情况,单例模式常见的两种实现方式如下

懒汉式:

class Test {
	private static Test _instance;

	private Test() {
	}

	/**
	 * 
	 * @return 返回Test唯一实例
	 */
	public synchronized static Test getInstance() {
		if (null == _instance) {
			_instance = new Test();
		}
		return _instance;
	}
}

饿汉式:

class Test {
	private static Test _instance = new Test();

	private Test() {
	}

	/**
	 * 
	 * @return 返回Test唯一实例
	 */
	public static Test getInstance() {
		return _instance;
	}
}

按照上面这种写法,几乎所有单例都需要这段基本一样的代码,本文将介绍另外一种实现,可实现代码的复用,实现技巧:将单例看成是一种性质,而JDK1.5+的注解这一特性能很好的帮助我们解决这一需求,将类标记为单例。

1. 首先定义单例注解,注解的作用就是将类标记为单例

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 单例注解,该注解只能作用在类上,不能作用在方法上
 */
@Target({ java.lang.annotation.ElementType.ANNOTATION_TYPE, java.lang.annotation.ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Singleton {
}

2. 定义对象工厂,用于解释我们的注解,并提供获取单例对象的方法

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * 对象工厂,用于解释我们的单例注解,并提供获取单例对象的方法
 * 
 * @author xxx
 * @version 2014-4-14
 */
public final class New {

	/**
	 * container to save Singleton
	 */
	private static volatile Map<String, Object> objs = new HashMap<String, Object>();

	/**
	 * 返回单例的静态方法,如果类没有用Singleton注解标记,则返回一个全新的实例
	 * 关于该方法线程安全
	 * @param clazz 
	 * @return the Singleton
	 */
	public static <T> T getInstance(Class<T> clazz) {
		String className = clazz.getName();
		synchronized (clazz) {
			/**
			 * whether used the Single Annotation
			 */
			if (clazz.isAnnotationPresent(Singleton.class)) {
				Object object = objs.get(className);
				if (object == null) {
					objs.put(className, newInstance(clazz));
				}
				return clazz.cast(objs.get(className));
			}
			return newInstance(clazz);
		}
	}

	private static <T> T newInstance(Class<T> clazz) {
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor();
			if (!constructor.isAccessible()) {
				constructor.setAccessible(true);
			}
			return constructor.newInstance();
		} catch (Exception e) {
			throw new NewInstanceException(e);
		}
	}
}

class NewInstanceException extends RuntimeException {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public NewInstanceException() {
		super();
	}

	public NewInstanceException(String message, Throwable cause) {
		super(message, cause);
	}

	public NewInstanceException(String message) {
		super(message);
	}

	public NewInstanceException(Throwable cause) {
		super(cause);
	}
}


注:单例类,不能包含带参数构造方法,而对于无参构造函数是否公有物要求

至此,我的基于反射机制的单例模式核心代码,已经实现完毕。


测试代码:

public class Main {

	public static void main(String[] args) {
		Test instance1 = New.getInstance(Test.class);
		Test instance2 = New.getInstance(Test.class);
		System.out.println(instance1.hashCode() == instance2.hashCode());
	}
}

@Singleton
class Test {
	private Test() {
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值