簡體   English   中英

何時使用構造函數,何時使用 getInstance() 方法(靜態工廠方法)?

[英]When to use a Constructor and when to use getInstance() method (static factory methods)?

  1. 我們應該何時以及如何使用構造函數

    Foo bar = new Foo();
  2. 我們應該何時以及如何使用 getInstance()(靜態工廠方法)

     Foo bar = Foo.getInstance();

這兩者有什么區別? 我一直使用構造函數,但是什么時候應該使用getInstance()呢?

每個人似乎都關注單例,而我認為問題實際上是關於構造函數與靜態工廠方法

這實際上是 Joshua Bloch 的第 1 條:考慮靜態工廠方法而不是Effective Java的構造函數

第 1 條:考慮靜態工廠方法而不是構造函數

一個類允許客戶端獲取自身實例的正常方式是提供一個公共構造函數。 還有另一種技術應該成為每個程序員工具包的一部分。 一個類可以提供一個公共靜態工廠方法,它只是一個返回類實例的靜態方法。 這是Boolean的一個簡單示例(原始類型boolean的裝箱原始類)。 此方法將布爾原始值轉換為Boolean對象引用:

 public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }

請注意,靜態工廠方法與設計模式中工廠方法模式不同[Gamma95,p。 107]。 此項中描述的靜態工廠方法在設計模式中沒有直接等效項。

一個類可以為它的客戶提供靜態工廠方法來代替構造函數,或者除了構造函數之外。 提供靜態工廠方法而不是公共構造函數既有優點也有缺點。

優點(引用本書):

  • 靜態工廠方法的優點之一是,與構造函數不同,它們有名稱。
  • 靜態工廠方法的第二個優點是,與構造函數不同,它們不需要在每次調用時都創建一個新對象。
  • 靜態工廠方法的第三個優點是,與構造函數不同,它們可以返回其返回類型的任何子類型的對象。
  • 靜態工廠方法的第四個優點是它們減少了創建參數化類型實例的冗長。

缺點(還是引用書上的):

  • 只提供靜態工廠方法的主要缺點是沒有公共或受保護構造函數的類不能被子類化。
  • 靜態工廠方法的第二個缺點是它們不容易與其他靜態方法區分開來。

您有兩個問題:什么時候應該調用getInstance()方法,什么時候應該創建一個?

如果您決定是否調用getInstance()方法,這很容易。 您只需要閱讀類文檔以了解何時應該調用它。 例如, NumberFormat提供了一個構造函數一個getInstance()方法; getInstance()方法會給你一個本地化的NumberFormat 另一方面,對於Calendar ,構造函數是受保護的。 必須調用getInstance()來獲得一個。

如果您正在決定是否創建getInstance()方法,您需要決定您要完成什么。 要么您希望人們調用您的構造函數(您正在創建單例工廠),要么您不介意(如上面的NumberFormat ,他們正在初始化一些對象以方便調用者)。


長話短說? 不要擔心在您自己的代碼中創建getInstance()方法。 如果到時候它們會派上用場,你就會知道。 一般而言,如果您可以調用類的構造函數,那么您可能應該這樣做,即使該類提供了getInstance()方法。

getInstance 方法的用途:

但大多數情況下,您的對象將是一個簡單的POJO,並且使用公共構造函數是最實用和最明顯的解決方案。

U1:從另一個類中獲取實例

返回不同類的實例:

public class FooFactory {
    public static Foo getInstance() {
        return new Foo();
    }
}

NumberFormat.getInstance方法會這樣做,因為它們實際上返回DecimalFormat實例。

U2:單例問題

單例模式限制了面向對象編程的許多好處。 單例通常具有私有構造函數,因此您不能擴展它們。 由於您將通過其 getInstance 方法訪問它而不引用任何接口,因此您將無法將其替換為另一個實現。

如果您可以同時使用兩者,那么這聽起來像是一個實現不佳的單例模式

如果您打算在您的系統中只有該類的一個實例,然后將構造函數設為私有,請使用第二個選項。

使用第一個允許構建類的多個對象。

但是不要給你的班級兩種可能性。

注意不要過度使用單例,只有在系統中真的只有一個實例時才使用它們,否則你會限制在其他項目中重用你的類的可能性。 能夠從項目中的任何地方調用 getInstance 聽起來很有趣,但這並不清楚誰真正擁有該實例:沒有人和/或所有人。 如果你在一個項目中有很多單身人士,你可以打賭這個系統設計得很差(通常)。 應謹慎使用單例,與適用於全局變量的建議相同。

我總是喜歡靜態工廠而不是常規構造函數的一種情況是,當我知道對象構造會很慢時。 我對構造函數進行了簡單的初始化,但是如果我需要創建一些繁重的東西,我將使用靜態方法並記錄行為。

單身人士是邪惡的。 我看到的圍繞它的問題與系統的重用或可擴展性無關(盡管我可以看到它是如何發生的),更多的是我無法計算我在一個系統中看到模糊錯誤的次數由單身人士產生的系統。

如果您確實需要使用單例,請確保它的范圍非常狹窄,即明智地限制系統中了解它的其他對象的數量。

暫無
暫無

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

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