单例模式,主要由以下几个模块组成:私有的静态对象实例,私有的构造方法(避免外部调用new对象,保证只有一个对象的实例),一个共有的静态获取对象的方法(供外部调用)。
代码如下:
懒汉式单例模式(在需要的时候,也即调用共有的静态获取对象的方法时才创建对象):
package SinglePattern;
public class LazySingle {
private static LazySingle newInstance = null;
private LazySingle(){
}
public static LazySingle getInstance(){
if(newInstance == null){
System.out.println("调用时创建对象。");
newInstance = new LazySingle();
}
return newInstance;
}
}
懒汉式单例模式是线程不安全的(比如两个线程同时执行getInstance方法,线程A执行到 newInstance = new LazySingle()的时候等待内存分配,此时线程B也执行到 if(newInstance == null),判断返回是true,那么程序中就可能出现两个对象),可以做如下改进:
优化一(用synchronized):
package SinglePattern;
public class LazySingle {
private static LazySingle newInstance = null;
private LazySingle(){
}
public static synchronized LazySingle getInstance(){
if(newInstance == null){
System.out.println("调用时创建对象。");
newInstance = new LazySingle();
}
return newInstance;
}
}
优化二(用synchronized,更加细粒度,即双重检验):
package SinglePattern;
public class LazySingle {
private static LazySingle newInstance = null;
private LazySingle(){
}
public static LazySingle getInstance(){
if(newInstance == null){
synchronized (LazySingle.class) {
if(newInstance == null){
newInstance = new LazySingle();
}
}
}
return newInstance;
}
}
优化三(用静态内部类,classloader机制在类加载的时候并不会加载静态内部类,也就不会创建对象的实例,只有当调用获取对象的方法时才会加载内部类,创建对象的实例):
package SinglePattern;
public class LazySingle {
private static LazySingle newInstance = null;
private LazySingle(){
}
private static class SingleHolder{
private static final LazySingle newInstance = new LazySingle();
}
public static final LazySingle getInstance(){
return SingleHolder.newInstance;
}
}
饿汉式单例模式(不管需不需要对象实例,在类加载的时候就创建好类的实例,利用classloader机制避免了线程安全的问题):
package SinglePattern;
public class HungrySingle {
private static HungrySingle newInstance = new HungrySingle();
private HungrySingle(){
}
public static HungrySingle getInstance(){
System.out.println("调用时已经创建好了对象。");
return newInstance;
}
}
总结:一般情况下使用饿汉式单例模式,在特定的懒加载模式下(初始化很耗费资源,但是并不常用)可以使用静态内部类的方式,其他情况下使用synchronized双重检验的模式。
参考文档:设计模式|菜鸟教程,《设计模式之禅》
上一篇:设计模式(四)——抽象工厂模式
下一篇:设计模式(六)——建造者模式