2009-12-06 49 views
-1

採取有人想填到一系列的網站獲取RSS流這個骨架類:值檢查類內部或外部的邏輯?

public class RSSStream extends Thread { 

    public RSSStream(String rssStreamName,String rssURL,int refreshTime){ 
     // constructor code goes here 
    } 
} 

現在,讓我們考慮refreshTime必須大於零且rssURL應該是一個有效的HTTP地址。

明顯的反射是在構造函數中有一些值檢查邏輯。然而,無論發生什麼,對構造函數的調用都會實例化Object。這意味着如果這些值不允許它完成它的工作,則該對象最終會變得毫無用處。這也意味着對象應該最終被拋棄或重用。

所以,這裏的一對夫婦對主題的問題:

  • 爲什麼有些班級實行再加上什麼可能是一個私有構造一個getInstance()方法?如果我記得清楚,一個例子就是GregorianCalendar。
  • 你會在什麼情況下使用這種相同的方法?
  • 在大多數情況下,你的構造函數中是否有檢查邏輯?
  • 如果是這樣,你是否將此應用於域模型的持久化上下文中使用的實體類?

您的全部答案是受歡迎的。瞭解最常見的做法將會很有趣。

回答

3

幾個最常見的事情:

  • 如果使用FactoryMethod對複雜對象的構造,你會通常有一個私人的構造,並通過工廠需要實例化。這支持與工廠交換施工策略。

  • 最清楚我是在構造函數中引發自定義(希望信息)異常,如果實例是不可能發生的:

    公共類Person {

    public Person(Integer id, String name) throws InvalidPersonException 
         if (name==null) throw new InvalidPersonException("You cant have a person without a name"); 
         ... 
    
  • 這可能在實體持久化對象中創建一個混亂,主要是因爲你希望這些對象是無邏輯的,並且因爲框架應該爲你處理 - 例如如果在hibernate中有一個包含(id,name)的bean,並試圖將其名稱保持爲非空名稱,那麼db引發的錯誤或您的配置應該足夠了。

2

如果檢查您需要執行的值可能會使對象實例處於損壞狀態,那麼您應該考慮創建一個工廠來生成您的實例。這將允許您在傳遞的參數無效的情況下拋出異常。

但是,如果您的對象在驗證失敗的情況下可以在構造函數中使用默認值「固定」,那麼使用默認值爲調用者提供無用但未損壞的對象。

+0

爲什麼不在構造函數中拋出異常? – 2009-12-07 10:33:48

2

如果您的構造函數拋出一個異常,則不會返回對您的對象的引用,因此該對象可以立即進行垃圾回收。所以你不是在浪費記憶。我認爲無論何時構建對象,特別是不可變對象,這都是您驗證的正確場所。

getInstance()是一個返回子類實例的工廠方法。根據具體情況,您在返回不同的子類時使用此方法。例如,Calendar.getInstance()在我的語言環境中返回一個GregorianCalendar,但如果我的語言環境設置不同,它可能會返回不同的實現。

對於各種圖案用於創建對象,檢查出http://en.wikipedia.org/wiki/Creational_pattern

希望這有助於

+0

非常明確,重點突出。謝謝。 – 2009-12-10 05:35:37

2
  • 我主要看到和使​​用的靜態getInstance()和私有的構造方法只是爲了使用Singleton模式。但是,Java的Calendar抽象類不是用於Singleton,而是使用此方法實例化具有默認時區和區域設置的默認實現(Gregorian)。可能這是因爲Calendar是抽象的,不能被實例化。 GregorianCalendar實際上有公共構造函數。
  • 在大多數情況下,我只是一個無參數的公共構造函數和setter方法,並將檢查邏輯和異常拋出放置在setter方法中。我經常使用Spring的依賴注入,如果沒有設置所有必需的屬性,@Required annotation可以讓容器拋出異常。
  • 我沒有在實體對象中應用這種邏輯,爲了簡單起見,我儘量保留所有的邏輯,並且嚴格地使它們成爲POJO。
+0

很多經驗都會在你的答案中出現。非常感謝您分享您的見解。 – 2009-12-11 14:51:07

2

在這種特殊情況下,我只是在構造函數中進行參數驗證,然後拋出IllegalArgumentException和描述性錯誤消息。該對象不會被創建,調用代碼將不得不被修復。

你也可以在getInstance()方法中做到這一點。使用getInstance()的一個原因是如果實例非常可共享,以減少您創建的對象的數量。例如,如果您可以擁有多個具有相同URL的RSSStream對象,則可以使用getInstance()來共享這些實例。 (這假設實例是不可變的。)

還有Builder模式。你必須叫RSSStream.Builder一個嵌套的內部類並說這樣的話:

RSSStream rss = new RSSStream.Builder.build(url) 
            .name("stack overflow") 
            .refreshTime(2) 
            .build(); 

這種模式使您的客戶端代碼更自我描述,並確保你永遠無法處於無效狀態的RSSStream(的方法構建器拋出IllegalArgumentException)。構建器足夠靈活,可以替換所有公共構造函數。我一般使用IllegalArgumentException,從構造函數或驗證方法(從多個構造函數中抽象錯誤檢查代碼)中拋出它。我已經開始將Builder方法用於更重要的公共API,並且非常喜歡它。

您當然可以在您的領域模型類中使用這些技術。

+0

在一個嚴重的應用程序中,我認爲連接的數量是有限的,所以共享是必要的。我對構建器模式不是很熟悉,所以非常感謝這個例子。謝謝。 – 2009-12-11 14:54:38

2

如果驗證失敗,需要驗證其參數的構造函數通常會拋出IllegalArgumentException。當構造函數拋出異常時,不需要擔心「中途初始化」對象。