使用反射破壞和管理單例模式

        Java中可以使用反射來創建類的實例,即使類的構造方法私有時,也可以創建,這樣就可能導致單例模式被破壞。比如下面非常純的單例模式:

//非常普通的單例模式
public class Singleton {

    private static final Singleton instance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        return instance;
    }

}

使用下面方法破壞單例:

public class SingletonKiller {
    public static void main(String[] args) throws Exception {

        /* 可以使用相對路徑,同一個包中可以不用帶包路徑 */
        Class s = Class.forName("com.piaohan.pattern.singleton.Singleton");
        Constructor ct = s.getDeclaredConstructor();

        /* true:使java不檢查訪問限制,即可以使用private方法 */
        ct.setAccessible(true);

        System.out.println(Singleton.getInstance());

        System.out.println(ct.newInstance());

        System.out.println(Singleton.getInstance() == ct.newInstance());

    }
}

結果如下:

com.piaohan.pattern.singleton.Singleton@67f1fba0
com.piaohan.pattern.singleton.Singleton@3fbefab0
false

反射破壞了單例模式,但是實際開發中影響不大,項目約定好了不允許這樣用就行了,很少有人會故意這麼寫,但是可以考慮使用這種方式結合工廠模式創建單例類,比如把所有要創建的單例類構造函數設置成私有,而正常寫邏輯就行。代碼如下:

//無狀態業務邏輯
public class SingletonService {

    // 私有構造函數,防止外部實例化
    private SingletonService() {

    }

    // 業務邏輯1
    public void method1() {

    }

    // 業務邏輯2
    public void method2() {

    }
}

使用下面工廠生成具體的邏輯類實例對象:
//單例工廠
public class SingletonFactory {

    private static Map<Class<?>, Object> objCache = new HashMap<Class<?>, Object>();

    public synchronized static Object getInstance(Class<?> clazz) throws Exception {
        Object singleton = objCache.get(clazz);
        if (singleton == null) {
            singleton = createInstance(clazz);
            objCache.put(clazz, singleton);
        }
        return singleton;
    }

    private static Object createInstance(Class<?> clazz) throws Exception {
        Constructor ct = clazz.getDeclaredConstructor();
        ct.setAccessible(true);
        return ct.newInstance();
    }
}

這樣,就不用每個類都手動寫一個單例模式了,當然,這裏只是思路,實際開發中要考慮性能,併發等問題。如果能夠使用spring,就可以替代類似這個功能了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章