1. 程式人生 > >設計模式之單例模式(二)

設計模式之單例模式(二)

單例模式

顧名思義,單例模式就是保證某個類只有一個例項。在計算機系統中,執行緒池、快取、日誌物件、對話方塊、印表機、顯示卡的驅動程式物件常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個印表機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到印表機中。每臺計算機可以有若干通訊埠,系統應當集中管理這些通訊埠,以避免一個通訊埠同時被兩個請求同時呼叫。

1.餓漢模式

public class HungrySingleton {
    //構造器私有化
    private HungrySingleton(){}
    private static  HungrySingleton singleton = new HungrySingleton();
    //靜態工廠方法返回實體類
    public static  HungrySingleton getInstance(){
        return  singleton;
    }

}

Singleton通過將構造方法限定為private避免了類在外部被例項化,在同一個虛擬機器範圍內,Singleton的唯一例項只能通過getInstance()方法訪問。

測試:

public class test {
    public static void main(String[] args) {
        //得到實體
        HungrySingleton singleton1 = HungrySingleton.getInstance();
        HungrySingleton singleton2 = HungrySingleton.getInstance();
        System.out.println("singleton1:"+singleton1);
        System.out.println("singleton2:"+singleton2);
    }
}

輸出結果:

可以看見是相同的控制代碼

但是!!!!!我們可以用反射生成構造私有化的類。如下:

public class test1 {
    public static void main(String[] args) {

        try {
            //反射獲取類
            Class c1 =Class.forName("design.singleton.HungrySingleton");
            Constructor[] constructors = c1.getDeclaredConstructors();
            //將構造器的Accessible設定為true
            AccessibleObject.setAccessible(constructors, true);
            //反射獲得兩個實體
            for (Constructor constructor:constructors){
                if(constructor.isAccessible()){
                    HungrySingleton singleton = (HungrySingleton)constructor.newInstance();
                    System.out.println("singleton1:"+singleton);

                }
            }
            for (Constructor constructor:constructors){
                if(constructor.isAccessible()){
                    HungrySingleton singleton = (HungrySingleton)constructor.newInstance();
                    System.out.println("singleton1:"+singleton);

                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

結果為:

表明其生成了兩個例項,所以單例模式是不考慮反射的情況下是單例模式。

2.懶漢模式

public class LazySingleton {

    // 私有構造
    private LazySingleton() {}

    private static LazySingleton single = null;

    public static LazySingleton getInstance() {
        if(single == null){
            single = new LazySingleton();
        }
        return single;
    }
}

懶漢模式在多執行緒中可能出現多個實體,所以使用時應該注意可以通過加類鎖,確保執行緒安全。