2017-06-20 138 views
4

假設你有一個名爲Person類和Person具有的屬性,如nameidage等反而在構造函數中設置這些值的,一個不Java:爲什麼要使用方法而不是構造函數?

new Person().withName("Lorem").withId("1234").withAge(29) 

with方法是呼叫到set方法,並返回對象,例如,

public Person withAge(int age) { 
    this.setAge(age); 
    return this; 
} 

在當前項目中,我看到了很多這樣的代碼,常與5-10鏈式調用不同with方法。這樣做的好處是什麼,而不是在構造函數中設置這些值?

+0

那種某種Builder,從來沒有這樣的具體模式,但如果你有很多optionnal值,我猜這可能是一個好主意。 (PS:你忘記了'withAge'中的return語句) – AxelH

+1

代碼更易讀:新的Person(「a」,「b」,「c」)不能很容易地指出a,b和c是什麼。 –

+0

如果我看看你的代碼,我可以看到你在哪裏設置名稱,ID和年齡。如果我看到「新人」(「Lorem」,「1234」,29)',我沒有得到那個信息。如果Java允許某些其他語言(比如C#和Swift)使用命名參數,那麼對這種鏈接的需求將會減少。這是我對Java的第一投訴,我不確定爲什麼沒有任何舉動來添加此功能,我可以看到。 – ajb

回答

2

我看到的一個優點是可讀性。

如果我們擴展的例子

new Person() 
.withName("Lorem") 
.withId("1234") 
.withAge(29) 
.withHeight(170) 
.withWeight(75) 
.withTaxId("1234"); 

如果我們不使用這種模式和使用,使用的時候,我們最終會很多參數沒有任何關於他們的描述的構造格局。

new Person("Lorem","1234",29,170,75,"1234"); 
3

這樣做而不是在構造函數中設置這些值有什麼好處?

1)重載

您可以管理您要設置很容易,如果你有很多的參數設定的值數,但也有一些optionnal,你不必創建具體構造函數或傳遞值爲null

new Person("name", 19); 
new Person("name", 19, address); 

new Person("name", 19, phone); 

(這些都是壞的榜樣;))

在你的情況下,你只需要調用所需的方法(同樣具有setter方法)。

2)Identitication

另外,具有很多參數中的方法/構造往往是難以閱讀,以確定每一個參數的上下文

new Person("frank", "John", "Emma"); 
person.withName("frank").withFather("john").withMother("Emma"); 

傳遞參數的方法/構造函數是無名的,你必須檢查簽名以瞭解你傳遞的是什麼。用這種符號,你有一個更詳細和可讀的代碼。 (再次,,與制定者相同)。

3)可連接的設定器 對於設定器也是這樣,但沒有可鏈接的功能。

person.setName("name"); 
person.setAge(19); 

person.withName("name").withAge(19); 

除了可讀性,我不認爲真的是有一定的改善,鏈需要該方法返回的實例本身,,在類本身給予redondant代碼return this; )。

+1

我同意,我從來沒有理解爲什麼這種方法鏈接是如此炒作。 – Henry

1

似乎有是2個大優勢:

1)靈活性:有了這個模式,你基本上可以選擇字段來填充和不填充。而使用構造函數時,您需要有多個構造函數才能實現相同。作爲Person可以

new Person().withName("Loren") 

或者也可以

new Person().withName("Loren").withAge(30) 

與一切空/默認。

在構造函數初始化的情況下,您必須爲這兩個構造函數創建2個構造函數。

public Person(String name){ 
    //code 
} 

public Person(String name, String age){ 
//code 
} 

2.)正如其他答案所述,可讀性。

new Person().withName("Loren").withAge(30).withId(567) 

new Person("Loren", 30, 567) 
2

它的所有可讀性和fluent interfaces更具可讀性。

雖然你的例子不是一個非常好的一個流暢的界面,你可以在Java part of the wikipedia article:找到:

Author author = AUTHOR.as("author"); 
create.selectFrom(author) 
     .where(exists(selectOne() 
        .from(BOOK) 
        .where(BOOK.STATUS.eq(BOOK_STATUS.SOLD_OUT)) 
        .and(BOOK.AUTHOR_ID.eq(author.ID)))); 

流利的接口是在API的設計非常先進的話題,經常來與某種Builder patternto avoid too big and too many constructors)或Facade pattern(以避免難以理解,主要是內部API)。

A 漂亮流利的API通常需要深入瞭解您的需求和非常好的計劃/準備階段。


請注意,使用流暢的API與編寫DSL密切相關。在這裏你可以通過Martin Fowler和一個擴展的例子,really good explanation流暢的接口,它的優點,缺點,理論等。

+1

在這裏,我知道我已經在某處看到了這個符號! – AxelH

+0

@AxelH你好,我添加了一些細節 - 沒想到答案仍然很受關注,所以我一開始並沒有做太多的努力 –

相關問題