内容简介
Singleton模式是我介绍的第二个设计模式,其理念与FactoryMethod模式不同,核心思想是在这个类中,永远只拥有一个实例对象。该类负责创建自己的对象,同时确保只有单个对象被创建。
实现
package test;
public class t2 {
private static t2 singleton1 = new t2();
//由此处创建一个新的对象
private t2(){}
//将构造函数私有化,就不会被实例化
public static t2 getInstance(){
return singleton1;
}
//通过这个代码获取唯一的实例对象
}
主要模式
- 懒汉式
- 饿汉式
- 双重检验锁
- 静态内部类
- 枚举
方法详解
- 懒汉式(基础版)
这种方法是最常见的,在创建实例之前都会先进行一个判断,代码也是比较基本的,但是最大的问题是它没有办法实现多线程的操作
package test;
public class t2 {
private static t2 instance;
private t2 (){}
public static t2 getInstance() {
if (instance == null) {
instance = new t2();
}
return instance;
}
}
- 懒汉式
这种方法相较于前一种方法就是多了synchronized将该线程锁住,其意义在于只有第一次调用的时候才会进行初始化,但是问题在于synchronized会影响程序的执行效率
synchronized的作用是当有多线程调用getInstance()时,如果有其他线程也在调用,则先等正在使用的线程结束再开始新的进程
package test;
public class t2 {
private static t2 instance;
private t2(){}
public static synchronized t2 getInstance() {
if (instance == null) {
instance = new t2();
}
return instance;
}
}
- 饿汉式
这种方法比较常见,相当于懒汉式执行效率更高,但是因为每一次操作都要初始化,垃圾信息更多
package test;
public class t2 {
private static t2 instance = new t2();
private t2 (){}
public static t2 getInstance() {
return instance;
}
}
- 双重检验锁
这种代码的实现难度比较高,双重判断加synchronized锁定实现,比较安全同时在多线程情况下仍能保持高效
package test;
public class t2 {
private volatile static t2 instance;
private t2 (){}
public static t2 getInstance() {
if (instance == null) {
synchronized (t2.class) {
if (instance == null) {
instance = new t2();
}
}
}
return instance;
}
}
- 静态内部类
这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
这种方法相较于饿汉式最大的不同在于,它的instance实例在是在Holder被调用时才会实例化,而不是像饿汉一样,一加载单例类时就进行实例化,这样的延时效果比起饿汉式要更加的合理化。
package test;
public class t2 {
private static class Holder {
private static final t2 instance = new t2();
}
private t2 (){}
public static final t2 getInstance() {
return Holder.instance;
}
}
- 枚举
这种方法最为简介高效,但是因为enum是比较新的内容,所以在大部分情况下看起来比较生疏
package test;
public enum t2 {
INSTANCE;
public void whateverMethod() {
}
}
总结
Singleton模式是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,在很多情况下可以广泛利用。