在某些情况下,比如设备驱动程序的对象,我们自始至终只需要1个对象,因为如果制造出多个实例就会导致许多问题产生,这就需要单件模式。
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
private static ChocolateBoiler uniqueInstance;
private ChocolateBoiler() {
empty = true;
boiled = false;
}
public static ChocolateBoiler getInstance() {
if (uniqueInstance == null) {
System.out.println("Creating unique instance of Chocolate Boiler");
uniqueInstance = new ChocolateBoiler();
}
System.out.println("Returning instance of Chocolate Boiler");
return uniqueInstance;
}
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
// fill the boiler with a milk/chocolate mixture
}
}
public void drain() {
if (!isEmpty() && isBoiled()) {
// drain the boiled milk and chocolate
empty = true;
}
}
public void boil() {
if (!isEmpty() && !isBoiled()) {
// bring the contents to a boil
boiled = true;
}
}
public boolean isEmpty() {
return empty;
}
public boolean isBoiled() {
return boiled;
}
}
3、用"双重检查加锁",在getInstance()中减少使用同步
但要注意:双重加锁方式不适应于1.4及更早版本的Java,很多JVM对volatile的实现会导致双重加锁失败。
一些问题:
1、在Java中,全局变量基本上是对对象的静态引用,单件模式确保类只有1个实例并提供全局访问,全局变量可以提供全局访问,但是不能确保只有1个实例。
2、单件继承:因为构造器是私有的,不能用私有构造器来扩展类,因此需要将其改为public或protected(这样就不算真正的单件了)。最好不要继承单件,因为会造成子类共享static的那个量。
3、类加载器:如果在程序中有多个类加载器,而且同时使用了单件模式,会导致同一个类被加载多次,会出现多个单件并存的怪异现象。解决办法是:自行指定类加载器,并指定同一个类加载器。
4、如果使用JVM1.2或之前版本,你必须建立单件注册表,以免垃圾收集器把单件回收。