使用情况:
一般当我们在程序只要生成一个类的实例时,我们就使用Singleton模式。
优点:
可控制实例数仅有一个,改进后可以控制实例的数量。
实现:
基本结构如下:
一个Simgleton的类中,一般包含如下几个关键点:
l Pirvate 的本实例引用
l Private 的够造方法
l 重写clone方法
程序模板如下:
package singleton;
/**
*SimpleSingleton.java
* Created on 7:06:43 PM Mar 1, 2009
*@author Quasar063501
*@version 0.1
*
*/
public class SimpleSingleton {
private static SimpleSingleton instance = null;
private SimpleSingleton() {
//只是为了在类的外部实例化
}
//synchronized防止多线程时竞争条件
public static synchronized SimpleSingleton getSingleton() {
if(instance == null) {
instance = new SimpleSingleton();
}
return instance;
}
//防止在“=”时和使用clone()时得到实例
public SimpleSingleton clone() throws CloneNotSupportedException{
throw new CloneNotSupportedException();
}
public void sayHello() {
System.out.println("Hello! I am "+getClass().getName()+".");
}
//用于测试,clone时抛出异常
// public static void main(String args[]) {
// SimpleSingleton s = SimpleSingleton.getSingleton();
// s.sayHello();
try {
SimpleSingleton s1 = s.clone();
s1.sayHello();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
/**
* java.lang.CloneNotSupportedException
* at singleton.SimpleSingleton.clone(SimpleSingleton.java:28)
* at singleton.SimpleSingleton.main(SimpleSingleton.java:40)
*/
}
// }
}
这是最简单的单例实现了,一般情况下,我们尽量使singleton的类没有子类,这样可以省去不少麻烦,不过,如果实现,也是可以的,但构造方法只能是protected的了。只能在包外保证单例。有三种方法,如下:
我们给出一种使用于没有反射机制的注册实现,其他的简要介绍。
1判断式
每次添加子类,必须修改父类的getInstance方法,不好!
public class Singleton {
private static Singleton instance = null;
protected Singleton() {
// ....
}
public static Singleton getInstance() {
if (instance == null) {
// getEnv表示系統環境變數
String style = getEnv("style");
if (style.equals("child1"))
instance = new ChildSingleton1();
else if (style.equals("child2r"))
instance = new ChildSingleton2();
else
instance = new Singleton();
}
return _instance;
}
// ....
}
2反射式(只适用于java这种有反射机制的语言)
public class Singleton {
private static Singleton instance = null;
protected Singleton() {
// ....
}
public static Singleton getInstance() {
if (instance == null) {
// getEnv表示環境變數
String style = getEnv("style");
try {
instance = (Singleton)
Class.forName(style).newInstance();
}
catch(Exception e) {
System.out.println(
"Sorry! No such class defined!");
}
}
return instance;
}
// ....
}
3具体实现的注册单例模式
子类的构造方法中,注册实例到map,在定义lookup方法,返回实例,具体代码如下:
父类:
package singleton;
import java.util.HashMap;
import java.util.Map;
/**
*SimpleSingleton.java
* Created on 7:06:43 PM Mar 1, 2009
*@author Quasar063501
*@version 0.1
*
*/
public class SimpleSingleton {
//用于储存singleton家族的一系列对象
private static Map<String, SimpleSingleton> instances= new HashMap();
private static SimpleSingleton instance = null;
protected SimpleSingleton() {
//保证包外单例
}
//synchronized防止多线程时竞争条件
public static synchronized SimpleSingleton getSingleton(String name) {
if(instance == null) {
instance = lookup(name);
}
return instance;
}
//防止在“=”时和使用clone()时得到实例
public SimpleSingleton clone() throws CloneNotSupportedException{
throw new CloneNotSupportedException();
}
//用于注册
public static void register(String name, SimpleSingleton instance) {
instances.put(name, instance);
}
//用于查找
private static SimpleSingleton lookup(String name) {
return instances.get(name);
}
public void sayHello() {
System.out.println("Hello! I am "+getClass().getName()+".");
}
}
俩个子类:
package singleton;
/**
*Singleton1.java
* Created on 7:22:25 PM Mar 1, 2009
*@author Quasar063501
*@version 0.1
*
*/
public class Singleton1 extends SimpleSingleton{
public Singleton1() {
register(getClass().getName(), this);
}
}
package singleton;
/**
*Singleton2.java
* Created on 7:24:51 PM Mar 1, 2009
*@author Quasar063501
*@version 0.1
*
*/
public class Singleton2 extends SimpleSingleton{
}
测试类:
package testsingle;
import singleton.SimpleSingleton;
import singleton.Singleton1;
import singleton.Singleton2;
/**
*TestSingle.java
* Created on 8:03:14 PM Mar 1, 2009
*@author Quasar063501
*@version 0.1
*
*/
public class TestSingle {
public static void main(String[] args) {
// SimpleSingleton s = new SimpleSingleton();
// s.sayHello();
//生成并注册
new Singleton1();
//通过父类得到子类
SimpleSingleton s1 = SimpleSingleton.getSingleton("singleton.Singleton1");
s1.sayHello();
new Singleton2();
SimpleSingleton s2 = SimpleSingleton.getSingleton("singleton.Singleton2");
s2.sayHello();
/**
* 输出: Hello! I am singleton.Singleton1.
* Hello! I am singleton.Singleton1.
* 保证了单例!
*/
}
}
后续将会更详细的讲解单例!