簡體   English   中英

單身模式

[英]Singleton Pattern

像我之前的問題一樣,這個問題引用了Effective Java 這次我有很多子問題。

  1. 特權客戶端可以借助AccessibleObject.setAccessible()方法反射性地調用私有構造函數。 如果您需要防范此操作,請修改構造函數。
    究竟如何調用私有構造函數? 什么是AccessibleObject.setAccessible()

  2. 您的專家對單身人士采用什么方法?

     // Approach A public class Test{ public static final Test TestInstance = new Test(); private Test(){ ... } . . . } // Approach B public class Test{ private static final Test TestInstance = new Test(); private Test(){ ... } public static Test getInstance() { return TestInstance; } . . . } 

    第二種方法是不是更靈活,以防我們每次都要檢查新實例或每次檢查同一個實例?

  3. 如果我嘗試克隆類/對象怎么辦?

  4. 單元素枚舉類型是實現單例的最佳方式。
    為什么? 怎么樣?

特權限制的cleint可以借助AccessibleObject.setAccessible方法反射性地調用私有構造函數。如果需要保護它,請修改構造函數。 我的問題是:如何調用私有構造函數? 什么是AccessibleObject.setAccessible?

顯然,類本身可以調用私有構造函數(例如,從靜態工廠方法)。 反過來,布洛赫正在談論的是:

import java.lang.reflect.Constructor;

public class PrivateInvoker {
    public static void main(String[] args) throws Exception{
        //compile error 
//      Private p = new Private();

        //works fine
        Constructor<?> con = Private.class.getDeclaredConstructors()[0];
        con.setAccessible(true);
        Private p = (Private) con.newInstance();
    } 
}

class Private {
    private Private() {
        System.out.println("Hello!");
    } 
}

2.專家對單身人士采取什么方法:

...

通常,第一個是受歡迎的。 第二個(假設您在返回新實例之前測試 TestInstance是否為null)以需要同步或線程不安全為代價獲得延遲加載。

當你的第二個例子沒有在聲明時將實例分配給TestInstance時,我寫了上面的內容。 如上所述,上述考慮無關緊要。

第二種方法是不是更靈活,以防我們每次都要檢查新實例或每次都是同一個實例?

它不是關於靈活性,而是關於何時產生創建一個(且唯一的)實例的成本。 如果你選擇a)它是在課堂加載時產生的。 這通常很好,因為只有在需要時才會加載類。

當你的第二個例子沒有在聲明時將實例分配給TestInstance時,我寫了上面的內容。 如前所述,在兩種情況下,Singleton都將在類加載時創建。

如果我嘗試克隆類/對象怎么辦?

單身人士不應該出於明顯的原因而允許克隆。 應拋出CloneNotSupportedException,除非由於某種原因實現Cloneable否則將自動拋出。

單元素枚舉類型是實現單例的最佳方式。 為什么? 如何?

這方面的例子在書中,正如理由一樣。 你不懂什么部分?

特權限制的cleint可以借助AccessibleObject.setAccessible方法反射性地調用私有構造函數。如果需要保護它,請修改構造函數。 我的問題是:如何調用私有構造函數? 什么是AccessibleObject.setAccessible?

您可以使用java反射來調用私有構造函數。

您的專家對單身人士采用什么方法:

我是使用枚舉來實際執行此操作的粉絲。 這也在書中。 如果這不是一個選項,那么選擇a更簡單,因為您不必檢查或擔心已經創建了實例。

如果我嘗試克隆類/對象怎么辦?

不明白你的意思? 你的意思是克隆()或其他我不知道的東西?

單元素枚舉類型是實現單例的最佳方式。 為什么? 如何?

啊,我自己的答案。 哈哈。 這是最好的方法,因為在這種情況下,java編程語言保證單例而不是開發人員必須檢查單例。 這幾乎就像單身人士是框架/語言的一部分。

編輯:我之前沒有看到它是一個吸氣劑。 更新我對此的回答 - 最好使用getInstance這樣的函數,因為你可以控制通過getter發生的事情,但如果每個人都直接使用引用,你就不能這樣做。 想想未來。 如果你最終做了SomeClass.INTANCE,然后你想讓它變得懶惰,所以它不會立即加載,那么你需要在它被使用的任何地方進行更改。

單身人士是一個很好的學習模式,尤其是作為入門設計模式。 但要注意,它們通常最終成為最常用的模式之一 有人認為它們是一種“反模式” 最好的建議是“明智地使用它們”。

有關這方面的很好的介紹,以及許多其他有用的模式(我個人認為策略,觀察者和命令比Singleton更有用),請查看Head First Design Patterns

Singleton(反)模式的第一條規則是不使用它 第二個規則是不要使用它 ,以便更容易獲得您希望多個其他對象共享的類的單個實例, 特別是如果它是這些類的依賴項。 改為使用依賴注入。 單身人士有一些有效的用途,但是人們會嚴重濫用他們,因為他們使用起來非常“容易”。 他們很難測試依賴於它們的類並使系統不靈活。

至於你的問題,我認為1,23都可以說“使用回答enum -singleton”。 然后你不必擔心構造函數accessiblity問題, clone() ing等。至於4 ,上面的內容對他們來說是一個很好的論據。 我還要問一下,您是否閱讀過有效Java中明確回答您問題的部分?

示例singleton lazy init:類main:

public class Main {

    public static void main(String[] args) {
        System.out.println(Singleton.getInstance("first").value);
        System.out.println(Singleton.getInstance("second").value);
        System.out.println(Singleton.getInstance("therd").value);
    }
}

班級單身人士:

public class Singleton {
    private static Singleton instance;
    public String value;

    private Singleton (String s){
        this.value =s;
    }
    public static Singleton getInstance(String param) {
        if (instance == null) 
            instance = new Singleton(param);
        return instance;    
    }
}

啟動應用程序時,控制台將包含下一個字符串

first
first
first

\\ | / 73

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM