设计模式系列 · 单例模式(最常见)

单例模式

关键点

1.构造函数不对外开放,一般为Private
2.通过一个静态方法或者枚举返回单例类对象
3.确保单例类的对象有且只有一个,尤其在多线程环境下
4.确保单例类对象在反序列化时不会重新构建对象

实现方式

1.懒汉模式

public void class Singleton {
    private static Singleton sInstance;
    private Singleton () {}
    public static synchronized Singleton getInstance () {
        if (sInstance == null) {
            sInstance = new Songleton ();
        }
        return sInstance;
    }
}

优点:使用时实例化,一定程度节约资源。
缺点:第一次使用需要实例化,速度较慢,每次调用 getInstance 都进行同步,造成不必要的开销。

2.Double Check Lock - DCL

public void class Singleton {
    private static Singleton sInstance = null;
    private Singleton () {}
    public static Singleton getInstance () {
        if (sInstance == null) {
            synchronized (Singleton.class) {
                if (sInstance == null) {
                     sInstance = new Songleton ();
                }
            }
        }
    }
    return sInstance;
}

优点:资源利用率高,第一次执行 getInstance 时才会被实例化,效率高。
缺点:第一次加载较慢,会由于Java内存模型的原因偶尔失败。高并发情况下也有缺陷,概率低。
造成失效原因(java编译器允许乱序以及JDK1.5之前java内存模型中Cache、寄存器到主内存回写顺序的规定,1-2-3的顺序无法保证,可能1-3-2.
JDK1.5或之后的版本加volatile规避)

1).给Singleton 的实例分配内存
2).调用Singleton() 的构造函数,初始化成员字段
3).将 sInstance 对象指向分配的内存空间

3.静态内部类单例模式

public void class Singleton {
    public static Singleton getInstance () {
        return SingletonHolder .sInstance;
    }
    private static class SingletonHolder {
        private static final Singleton sInstance = new Singleton ();
    }
}

优点:保证线程安全,确保唯一性,同时延迟了单例的实例化,推荐。

4.枚举单例

public enum SingletonEnum {
    INSTANCE;
    public void doSomething () {
       System.out.println ("do some.");
    }
}

在上述的几种单例模式中,反序列化时它们都会重新创建对象,枚举不存在此问题。

5.使用容器作为单例模式

public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String, Object> ();

private SingletonManager () {}
public static void registerService (String key, Object instance) {
    if(!objMap.containsKey(key) ) {
        objMap.put(key ,instance);
    }
}

public static Object getService (String, key) {
    return objMap.get(key);
    }
}

统一管理多种单例类型,降低耦合。

总结
优点:减少内存开支,性能开销,避免对资源的多重占用
*注意点:1) 拓展困难 . 2)若持有Context,防止内存泄露问题,传入Application Context. *

发布了24 篇原创文章 · 获赞 7 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章