登记单式单例模式研究

zbw 04-02-11
    

在《JAVA与模式》中,讨论了一种登记单式的单例模式,目的是为了能够继承,我没有太看明白书中所说的继承是为了继承“单例”的特性还是为了继承那个能够实现单例特性的Class的其他特性。反正在书里的代码里,子类的构造函数必须是public的,这样的类当然可以被new一个新的实例,因此有不少问题。

我于是打算自己做个例子,目的如下:
1、单例的特性与一般对象的特性分开
2、需要单例的对象,都不能被new
3、不要有多余的开销。

在一般的例子中,构造函数要么是public,要么是private,其实他也可以是protected的。于是我在系统中建一个signlaton包,这个包里只有一个类GetSignlaton可以通过getInstance()对外提供自己的实例,其他的对象,则需要通过这个GetSignlaton得到。

代码如下:

//管理单例类
package signlaton;
import java.util.Hashtable;
public class GetSignlaton {
private static GetSignlaton gs;
private static Hashtable ObjList;
private GetSignlaton(){}
public static GetSignlaton getInstance(){
if(gs==null){
gs=new GetSignlaton();
}
return gs;
}
public Object getObj(String name){
if(ObjList==null){
ObjList=new Hashtable();
}
if(ObjList.get(name)==null){
try{
ObjList.put(name,Class.forName(
"signlaton."+name).newInstance());
} catch(Exception e){
}
}
return ObjList.get(name);
}
}

//某一个具体的单例类
package signlaton;
public class SignObj {
private String t=
"";
protected SignObj(){}
public void setT(String v){
t=v;
}
public String getT(){
return t;
}
}

//测试类
package test;
import signlaton.*;
public class SignTest {
public static void main(String[] args) {
GetSignlaton gs=GetSignlaton.getInstance();
SignObj so=(SignObj)gs.getObj(
"SignObj");
so.setT(
"123");
System.out.println(so.getT());
SignObj so2=(SignObj)gs.getObj(
"SignObj");
so2.setT(
"1234");
System.out.println(so.getT());
System.out.println(so2.getT());
}
}

    

1
zbw
2004-02-11 19:42

不好意思
public static GetSignlaton getInstance()
应该改成
synchronized public static GetSignlaton getInstance(){

banq
2004-02-17 22:19

比较有意思的做法。

你这个类似ServiceManager之类的东东。我感觉这种做法在实际中可能应用机会不是很多。

使用Singleton要非常小心,容易将J2EE的多线程环境变成单线程,虽然做起来方便,但是性能却下降多,这个例子中登记对象都将是全局唯一实例,这种情况在实际中也很少有,特别在集群环境中,Singleton几乎没有什么作用,Singleton在我的实践中基本是用在配置文件读取上。

zbw
2004-02-18 13:01

我的这个研究只是针对《JAVA与模式》里的例子的。
至于这样的程序的使用环境,我想应该与J2EE无关。或者说,这样的程序,也是在“容器”这个层面上使用的。

banq
2004-02-18 13:09

是的,zbw这个分离的思想是非常正确的,看来你已经体会到模式的精髓了。