题目:设计一个类,我们只能生成该类的一个实例。
思路:
1.饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法)
优点 | 1.线程安全 。2.在类加载的同时已经创建好一个静态对象,调用时反应速度快。 |
缺点 | 资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化 |
2.双重检测:单例实例在第一次被使用时构建,延迟初始化,加锁synchornized。
优点 | 资源利用率高,不执行getInstance()就不被实例,可以执行该类其他静态方法 |
缺点 | 第一次加载时反应不快,由于java内存模型一些原因偶尔失败 |
综上所述,单例模式的注意事项有:
第一、尽量使用懒加载,资源利用率高;
第二、双重检索实现线程安全;
第三、构造方案为private;
第四、定义静态的 SingletonPattern instance对象和getInstance()方法。
基于以上思路,java参考代码如下:
package Designpatterns;
//饿汉式单例类.在类初始化时,已经自行实例化
public class SingletonPattern {
//属性和方法
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//私有的默认构造函数
private SingletonPattern(){};
//已经自行实例化
private static final SingletonPattern single=new SingletonPattern();
//静态工厂方法
public static SingletonPattern getInstance(){
return single;
}
/* public static void main(String[] args){
//SingletonPattern sin1=new SingletonPattern();
SingletonPattern sin1=SingletonPattern.getInstance();//获得单例
SingletonPattern sin2=SingletonPattern.getInstance();//获得单例
sin1.setName("simple");
sin2.setName("senbao");
System.out.println(sin1==sin2);
System.out.println(sin1.getName());
System.out.println(sin2.getName());
}*/
}
package Designpatterns;
//懒汉式单例类.在第一次调用的时候实例化
public class SingletonPattern2 {
//属性和方法
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
private SingletonPattern2(){};
//注意,这里没有final
private static SingletonPattern2 sin2=null;
// public volatile static SingletonPattern2 sin2;
public static SingletonPattern2 getInstance(){
if(sin2==null){
synchronized (SingletonPattern2.class){//
if(sin2==null){//判断两次都为空,才创建
sin2=new SingletonPattern2();
}
}
}
return sin2;
}
public static void main(String[] args){
//SingletonPattern sin1=new SingletonPattern();
SingletonPattern sin1=SingletonPattern.getInstance();//获得单例
SingletonPattern sin2=SingletonPattern.getInstance();//获得单例
sin1.setName("simple");
sin2.setName("senbao");
System.out.println(sin1==sin2);
System.out.println(sin1.getName());
System.out.println(sin2.getName());
}
}
参考:
https://mp.weixin.qq.com/s?__biz=MzI5MzYzMDAwNw==&mid=2247483950&idx=1&sn=57ead90d8305f7c8c07a8764f02d852a&scene=19#wechat_redirect
https://blog.csdn.net/wallwind/article/details/7250708
http://www.cnblogs.com/whgw/archive/2011/10/05/2199535.html