2014-01-15 141 views
26

我正在考慮爲我的應用程序提供的解決方案。情況如下:我有一個類,它帶有一個方法,它將ObjectA作爲輸入參數並調用幾個小方法,這些方法中的每一個都需要ObjectA的某些部分(它們不重疊,即method1()需要ObjectA.field1ObjectA.field2,method2()需要ObjectA.field3等等......)現在的問題是:鑑於通用的良好代碼實踐和性能,最好將ObjectA傳遞給這些方法中的每一個,以便它們可以自行提取它們需要的值,或者更好傳遞它們的值?我的意思是:傳遞整個對象vs傳遞對象的屬性

method1(ObjectA); 
method2(ObjectA); 

method1(Object1.getField1(), ObjectA.getField2()); 
method2(ObjectA.getField3()); 

感謝您的答案!

+5

我覺得第一個選項是更好..外部世界不需要知道你的函數內部與對象..這樣做(即哪些領域它訪問。) – TheLostMind

+4

這完全是你的需要。如果您不希望其他方法修改對象的字段,則不要傳遞對象引用。只需傳遞所需的值。如果不是,那麼最好傳遞對象引用,並在需要時使用它的值,而不是在方法調用中添加那麼多參數。 – SudoRahul

+1

這是一個很好的做法,使代碼儘可能簡單易懂和清晰。在這種情況下,我懷疑沒有性能差異,或者它太小而無法衡量。 –

回答

28

請記住,使用您的代碼,您實際上並未傳遞ObjectA。也就是說,您將參考類型傳遞給ObjectA,因此在性能註釋中,傳遞String對象引用和ObjectA對象引用之間的差異可以忽略不計。

的方式我會寫它

我會通過整個對象,如果該方法是恰當的類。我的推理是儘可能地分解課堂知識。我的意思是以下。

public void doSomethingRelatedToTheClass(String param) 
{ 
    // Do something with param. 
} 

我的第一個批評是這種方法假定輸入是正確的字段。我的第二個,就是現在,這個類調用此代碼需要知道一點點關於這個方法,因爲它有這樣稱呼它:

doSomethingRelatedToTheClass(myObject.getValue()); 

而這句話的意思是,如果你發現另一的ObjectA成員工作這個方法裏面更好,或者您要訪問的ObjectA其他成員,並更改doSomething(),以反映這種變化,你也需要改變方法調用,以:通過傳遞

doSomethingRelatedToTheClass(myObject.getOtherValue(), myObject.getValue()); 

所以整個對象,將這些細節抽象出來,並且該方法可以處理它;即:

doSomethingRelatedToTheClass(myObject); // Doesn't need to know what you do with it. 

public void doSomethingRelatedToTheClass(ObjectA object) 
{ 
    String val = object.getValue(); 

    String otherVal = object.getOtherValue(); 
} 

當更改一個類,在其他類別的變化的結果,這就是所謂的Shotgun Surgery反模式。

編輯

我有機會在這裏查看我的回答,我已經修改了我原來的答覆略有因爲我相信它不是爲所有情況下的最佳解決方案。如上所述,如果某個方法與某個類具體相關,那麼該類(或者更優選地,其超類或實現的接口[s])的實例應該是參數。

現在不是這種情況的時候,功能可能是通用的。泛型函數的一個例子可能是:

public String[] findNouns(String sentence); 

在這種情況下,發現在一個句子中的名詞可能適用於大量的使用案例,而不僅僅是你所定義的用例。因此,傳遞價值是唯一明智的方法,因爲否則,你將兩個邏輯連接在一起,這兩個邏輯沒有直接的關係。名詞和你定義的任意對象的發現。

總結

  • 如果該方法是與對象相關的邏輯,通過在對象

  • 如果該方法無關與對象,並且對象只是將它用作實用函數,然後傳遞值並一般地命名該函數。

+4

+1爲詳細答案..:P – TheLostMind

+1

可能出現的一個問題是,通過將整個ObjectA傳遞給函數定義,每個調用API的測試函數都需要實例化一個包含所有字段的Fake ObjectA。即使函數只使用這些字段的一個子集。然後,如果在ObjectA類上添加一個字段,即使實現沒有真正改變,也需要更改所有這些假對象。這是可以通過使用工廠存根來避免的,但需要更多的代碼。 –

+0

另一件事是,在我目前的項目中,我看到很多遺留代碼傳遞了太多的數據。如果需要一個屬性,並且你正在傳遞一個完整的對象,以防萬一某天你需要其他屬性... YAGNI – kiedysktos

3

我想說,這取決於。如果一個方法對參數進行操作而不是要求整個對象,則該方法可能會更清晰和更通用。有時候你已經準備好了論據(例如,xy),並且必須首先將它們聚合成例如一個Point爲了能夠調用該方法。有時你有一個不相關的對象(例如,一些ImmutablePoint,顯然不是延伸java.awt.Point),並且必須提取座標並創建一個要傳遞的對象。

通常,如果傳遞的對象是正確的抽象,那麼將它作爲一個整體傳遞是一條可行的路。這不是一個性能問題,而是關於可讀性和可維護性。另請參閱Law of Demeter,這可能導致對傳遞對象的鬆散依賴。

4

讓我們來看一個場景。現在這可能或可能不是你的情況,但它說明了一點。

可以說你的情況下,field1和field2是兩個整數,method1將它們相加並返回結果。

如果您傳入對象,那麼該方法只能總結這兩個字段。該方法現在也與這些對象緊密結合。另一方面,如果只傳遞字段,這種情況下的兩個整數就會變得更通用。現在您可以對任意2個任意整數進行求和,而不管它們在哪個對象上。

一般來說,儘可能少地暴露你的對象到其他方法和類。這促進了鬆耦合。

例外

AS maaartinus指出如果例如Field 1和場2分別爲點與方法1來計算這兩個點之間的距離,那麼我不得不同意,傳遞兩個點會比使2的xy整數對更好(4個參數)

希望這有助於