2012-06-18 44 views
2

毫無疑問,這已被問及在這裏回答了十幾次,但我無法找到滿意的答案。只允許父廠方法實例化子類

我有一個類的家庭,我只想通過像這樣的靜態方法(我可能在這裏輸入錯別字,而不嘗試編譯)輸入的抽象父類實例化。

public abstract class Papa { 
    public static Papa newInstance() { 
     String strClass = Papa.figureOutTheNameOfChildClassToInstantiate(); 
     Papa papa = (Papa) Class.forName(strClass).newInstance(); 
     return papa; 
    } 
    public abstract void doSomething(); 
    ... 
} 
public class Child extends Papa { 
    public void doSomething() { /* Do something */ } 
} 

這或多或少是我現在擁有的。我希望做的是確保Child只能通過工廠方法Papa.newInstance()實例化。我試圖通過將Child的無參數構造函數設爲私有,但Papa無法實例化它。

所以,我的問題是,我如何確保子實例只能通過工廠方法Papa.newInstance()創建?

回答

3

如果您絕對肯定地想要強制執行此操作,請給Papa一個受保護的構造函數,該構造函數採用Xyzzy類型的參數。使Xyzzy成爲Papa中受保護的內部課程。給它一個私人的構造函數。現在,只有Papa可以創建Xyzzy的實例。由於您需要Xyzzy的實例來調用Papa的構造函數,並且由於Papa的子類必須從其構造函數調用其構造函數,所以您需要一個Xyzzy實例來調用Papa的任何子類的構造函數。因此,只有Papa可以調用其子類的構造函數。即使Xyzzy沒有做任何事情。

子類可能會泄漏它們的Xyzzy實例,這將允許其他代碼調用子類構造函數。但是你也可以通過使用單一使用來限制這一點,並且只能在單個靜態工廠調用的上下文中使用。

但說實話,我不打擾!

+0

在內部類使用私有的構造是不是一個好主意 - 這迫使Java編譯器生成存根構造帶更多的知名度所以外部類可以實例化它們... – thkala

+0

實際上,如果不是因爲直到現在我已經直接在我的項目中實例化Child(和它的兄弟姐妹),現在我不會打擾它想要識別並刪除所有這些直接實例,並強迫自己始終使用未來的工廠方法。但即使如此,我仍然可以沒有所有的大驚小怪... –

+0

對於這樣的事情,類似Checkstyle的東西可能是謹慎的選擇。有一天,我們將擁有一種語言,它具有足夠強大的類型/訪問系統來執行您想要做的事情,但在Java中這樣做似乎可能會導致Lovecraftian。 –

3

幾個可能的選擇:

  1. 用於子類構造函數的默認可見性並把它們放在同一個包父類。這具有的缺點是這些類可以在同一個包中被其他類包括任何「兄弟」類來實例化。

  2. 讓父類中的所有子類爲nested classes。將它們標記爲private static將使它們僅對父類可見。不幸的是,這也意味着有所有類的代碼在同一個文件...