1.使用场景:
单例模式的作用主要是保证一个类只有一个实例,并且提供一个访问这个实例的全局访问点,通常在以下的场景中使用:
1.读取配置文件
2.设计数据库连接池等等
2.UML表示
从上图中可以看出,单例模式结构图中只包含了一个单例的角色。
3.代码实现
常见的单例模式总共有6种,下面分别对这6种单例模式进行实现:
3.1 懒汉式
特点:懒汉式加载,能够实现延时加载,缺点是调用的效率不高。
public class Lasy {
private static Lasy s;
public Lasy() {
}
public static synchronized Lasy getInstance(){
if (s==null){
s=new Lasy();
}
return s;
}
}
3.2 饿汉式
特点:饿汉式加载,线程安全,效率极高。
public class Hungry {
private static Hungry instance=new Hungry();
public Hungry() {//防止被反射创建
if(instance!=null) throw new RuntimeException();
}
public static Hungry getInstance(){
return instance;
}
}
3.3 双重检测
特点:减少了锁的粒度,比懒汉式更有效率。
public class DoubleCheck {
volatile private static DoubleCheck instance=null;
public static DoubleCheck getInstance() throws InterruptedException {
if(instance==null){
Thread.sleep(300);
synchronized (DoubleCheck.class){
if(instance==null){
instance=new DoubleCheck();
}
}
}
return instance;
}
}
3.4 枚举方式
特点:
通过枚举的方式实现单例,缺点是无法实现懒加载。
public enum EnumSingleton {
INSTANCE;
public void singletonOperation(){
//功能处理
}
}
3.5 内部类方式
特点:
类加载的过程是线程安全的,所以线程安全。
public class StaticInner {
private static class InnerClass{
private static final StaticInner instance=new StaticInner();
}
public static StaticInner getInstance(){
return InnerClass.instance;
}
}
3.6 序列化和反序列化实现单例
特点:
添加readResolve()方法,防止序列化和反序列化机制对单例的破坏,具体可以查看:http://www.hollischuang.com/archives/1144
public class BetterLasy implements Serializable{
private static BetterLasy s;
public static synchronized BetterLasy getInstance(){
if (s==null){
s=new BetterLasy();
}
return s;
}
private Object readResolve(){
return s;
}
}
最后附上代码的连接:
https://github.com/MemoryExplosion/design_pattern_review/tree/master/src/java/singleton