2010-03-05 62 views
5

考慮下面的類是否應類方法也接受參數或使用類屬性

public class Class1 
{ 
    public int A { get; set; } 
    public int B { get; set; } 

    public int GetComplexResult() 
    { 
     return A + B; 
    } 
} 

爲了使用GetComplexResult,這個類的一個消費者必須知道調用方法之前設置AB。如果GetComplexResult訪問許多屬性來計算其結果,如果消費者未首先設置所有適當的屬性,則這可能導致錯誤的返回值。所以,你可能會這樣寫類這樣反而

public class Class2 
{ 
    public int A { get; set; } 
    public int B { get; set; } 

    public int GetComplexResult(int a, int b) 
    { 
     return a + b; 
    } 
} 

這樣,呼叫者GetComplexResult被強制在所有需要的值傳遞,確保預期回報值計算正確。但是,如果有許多所需的值,參數列表也會增長,這看起來也不是很好的設計。它似乎也打破了將A,BGetComplexResult封裝在一個類中的觀點。我甚至可能會試圖使GetComplexResult成爲靜態的,因爲它不需要類的實例來完成它的工作。我不想去製作一堆靜態方法。

是否有術語來描述這兩種創建類的不同方式?他們都似乎有優點和缺點 - 有沒有我不明白,應該告訴我,一種方式比另一種更好?單元測試如何影響這個選擇?

回答

5

如果您使用現實世界的例子,答案會變得更清晰。

public class person 
{ 
    public string firstName { get; set; } 
    public string lastName { get; set; } 

    public string getFullName() 
    { 
     return firstName + " " + lastName; 
    } 
} 

實體對象的一點是,它包含一個實體的信息,並能做到操作的實體需要做的(基於它所包含的信息)。所以是的,在某些情況下某些操作無法正常工作,因爲實體尚未完全初始化,但這不是設計失敗。如果在現實世界中,我問你一個尚未命名的新生兒的全名,那也將失敗。

如果某些屬性對於執行其工作的實體是必不可少的,則它們可以在構造函數中初始化。另一種方法是有檢查實體是否在其中一個給定的方法可以被調用狀態的布爾值:

while (person.hasAnotherQuestion()) { 
    person.answerNextQuestion(); 
} 
+0

我總是嘗試調用getter而不是直接訪問成員,並在getter中記錄一條消息,如果我返回一個空值。我曾經使用斷言,但後來我們發現一些客戶在生產(!)中啓用斷言的情況下運行。 – TMN 2010-03-05 20:17:07

1

一個良好的設計原則是要確保所有構造函數初始化對象有效狀態,所有然後屬性設置器和方法強制執行有效狀態。這樣就不會有任何對象處於無效狀態。

如果AB的默認值,這是0不是產生從GetComplexResult一個有效的結果有效狀態,則應在初始化AB爲有效狀態的構造。

0

如果某些字段永遠不允許爲空,那麼您通常會將它們的參數設置爲類構造函數。如果您並不總是一次提供所有必需的值,那麼使用構建器類可能會有所幫助。

例如:

public Builder { 
    private int a; 
    private int b; 

    public Class1 create() { 
     // some validation logic goes here 
     // to make sure we have everything and 
     // either fill in defaults or throw an error 
     // if needed 
     return new Class1(a, b) 
    } 

    public Builder a(int val) { a = val; } 
    public Builder b(int val) { b = val; } 
} 

此構建然後可以如下使用。

Class1 obj1 = new Builder().a(5).b(6).create(); 

Builder builder = new Builder(); 
// do stuff to find value of a 
builder.a(valueOfA); 
// do stuff to find value of b 
builder.b(valueOfB); 
// do more stuff 
Class1 obj2 = builder.create(); 
Class2 obj3 = builder.create(); 

這個設計允許你鎖定實體類到適當的程度,同時還允許靈活的構造過程。它還打開了通過其他實現定製構建過程而不改變實體類合同的大門。

相關問題