一、单件模式简介
使用单件模式的意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单件模式适用于当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
单件模式有很多优点:1、对唯一实例的受控访问;2、缩小命名空间;3、允许对操作和表示的精化;4、允许可变数目的实例;5、比类操作更灵活。
单件模式的类图如下:

二 、JDK中的单件模式
在jdk中使用单件模式的类不少,这里的例子来自java.awt.Desktop。当要对桌面进行操作的时候,我们不能自行创建新的桌面,只能使用操作系统现有的唯一桌面,这种情况很适合使用单件模式,当我们需要访问此桌面时,可以调用方法getDesktop。
java.awt.Desktop实现单件模式的关键代码如下:
public class Desktop {
private DesktopPeer peer;
private Desktop() {
peer = Toolkit.getDefaultToolkit().createDesktopPeer(this);
}
public static synchronized Desktop getDesktop(){
if (GraphicsEnvironment.isHeadless()) throw new HeadlessException();
if (!Desktop.isDesktopSupported()) {
throw new UnsupportedOperationException("Desktop API is not " +
"supported on the current platform");
}
sun.awt.AppContext context = sun.awt.AppContext.getAppContext();
Desktop desktop = (Desktop)context.get(Desktop.class);
if (desktop == null) {
desktop = new Desktop();
context.put(Desktop.class, desktop);
}
return desktop;
}
//其他一些方法
}
三、关于单件模式的思考
单件模式的实现方式并不复杂,几乎所有单件模式的实现代码与上面的代码十分类似,这里给出实现单件模式的一般代码:
public class Singleton {
//构造函数是私有的
private Singleton(){}
//static关键字,整个类只会有一个实例
private static Singleton instance = new Singleton();
//这里提供了一个供外部访问本class实例的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
或者:
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
注意,在我们具体实现单件模式的时候还是有一些细节需要注意的,因为对象创建的方法,除了使用构造函数之外,还可以使用Object对象的clone()方法,因而在Singleton中也要注意这一点。如果Singleton类直接继承于Object,因为继承于Object的clone()方法仍保留有其protected修饰,因而不能够被其他外部类所调用,所以可以不用管它,但是如果Singleton继承于一个其他的类,而这个类又有重载clone()方法,这时就需要在Singleton中再重载clone()方法,并在其中抛出CloneNotSupportedException,这样就可以避免多个Singleton的实例被创建了。