java教程:学会Java设计模式成为高手分享java单实例模式
本文主要讲解java单实际设计模式:以前我对单实例模式的理解不够深入,今天就好好学习了下。之前我的印象中,单实例是这样实现的,私有化构造函数,提供私有静态的实例引用,并提供静态方法getInstance()来返回实例对象,若实例对象引用为null,则重新创建,否则直接返回。

其实,单实例远没有这么简单。由于Java多线程机制的存在,所以可能存在多个线程同时调用getInstance()去访问静态实例引用,两个线程的数据共享就存在线程安全问题,可能另一个线程已经改变了静态实例引用的值,所以必须使用synchronized来实现线程同步。由于线程同步会占用很大的系统开销,所以为了性能,又必须考虑只在实例尚未创建才考虑线程同步,即“双重检查机制”。
但是还有一个问题,由于网络类加载器的存在以及命名空间可以冒充,而同一命名空间的类拥有彼此访问的特殊权限,所以class文件可能存在潜在的安全问题,sun的做法是把class之间彼此访问的特殊权限授予给由同一类加载器加载的同一命名空间下的类,即“运行时包”的概念。换句话就是:由同一类加载器加载且同包下的类才有彼此访问的特殊权限。更通俗的讲,同一个类如果由不同的类加载器加载,得到的也不是同一个类,他们彼此不能互相访问。所以还要考虑多加载器的情况。我的做法是采用加载Singleton类的当前线程的类加载器作为创建单实例的默认加载器,从而统一类加载器。
还有一个问题,不得不考虑,那就是反序列化。一个java对象序列化到另一个介质,然后再根据这个介质可以反序列化N多个这个对象,所以我们要实现Serializable接口,实现它的readResolve方法,方法实现里调用我们Singleton类的静态方法getInstance()来返回实例,从而阻止反序列化多个实例情况的发生。
最后就要考虑我们这个Singleton类的重用性,因为真正的系统中可能会有很多类需要实现单实例,所以我们getInstance()方法的返回值应该改为Object,我刚开始想用泛型T来实现,可是一直报错:说T不是一个静态成员变量,无奈只好另辟蹊径。然后我们需要接受一个类名的参数,通过当前类的类加载器来获取待创建实例的class类型,具体见上面代码,然后根据Java反射机制去创建实例。由于不知道如何使用泛型来实现,所以唯一美中不足的是,只能返回Object类型,用户得到实例后还需进行强制转换成想要的类型。如果有谁知道怎么实现自动类型转换或者我有哪里说的不是很严谨,请不吝赐教,不胜感激!!!
附带源码:
/**
* 单实例V1.0
* @author Lanxiaowei
* @creatTime 2011-10-09 21:28
*
*/
public class Singleton implements Serializable{
private static Object singleton = null;
/**
* 类名(包含完整包名)
*/
protected static String className;
private Singleton(){}
public static Object getInstance() {
//对象未创建才保持同步以保证性能
if (null == singleton){
//考虑多线程安全问题
synchronized (Singleton.class) {
if (null == singleton){
try {
singleton = getClass(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
return singleton;
}
/**
* 保证即使多次反序列化,得到的也是单实例
*/
protected Object readResolve() {
return getInstance();
}
/**
* 始终使用当前线程的类加载器来加载类
*/
protected static Class getClass(String className) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader == null) {
classLoader = Singleton.class.getClassLoader();
}
return classLoader.loadClass(className);
}
}
好,今天就写到这里,困咯,睡觉~~~~~
本文来源 我爱IT技术网 http://www.52ij.com/jishu/105.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
