2010-08-03 272 views
5

我有一個類包含10個方法,除了一個關鍵事件外,它們的功能幾乎相同。兩個例子如下:刪除重複


Public String ATypeOperation(String pin, String amount){ 
    doSomething(); 
    doMoreStuff(); 
    requestBuilder.buildATypeRequest(pin, amount); 
    doAfterStuff(); 
} 
 


Public String BTypeOperation(String name, String sex, String age){ 
    doSomething(); 
    doMoreStuff(); 
    requestBuilder.buildBTypeRequest(name, sex, age); 
    doAfterStuff(); 
} 
 

正如你從上面的方法看,他們是從調用由requestBuilder提供不同的方法除了類似。其餘8個也類似。這裏有很多重複的代碼。我覺得有更好的方法來實現這一點,但不知道如何。任何意見和建議表示讚賞。

感謝, 薩拉

+1

您的請求是否真的在方法中使用? – helpermethod 2010-08-03 07:20:55

+0

@Helper是的。你可以說它用在doAfterSuff()中; – sarahTheButterFly 2010-08-03 07:23:40

回答

5

使用類似RequestBuilder,接受所有這些類型的參數:

public RequestBuilder { 
    // setters and getters for all properties 

    public Request build() { 
     doStuff(); 
     Request request = new Request(this); 
     doAfterStuff(); 
     return request; 
    } 
} 

然後

new RequestBuilder().setAge(age).setName(name).build(); 
+0

我在這裏有一個問題。當使用RequestBuilder()的客戶端時,他怎麼知道他應該設置什麼參數?以我的帖子中的兩種方法爲例,我不得不要求客戶選擇設置5個可能參數中的2個。我們如何確定客戶端不會設置錯誤的參數? – sarahTheButterFly 2010-08-04 00:41:21

+0

它設置任何它想要的(有'在手')。如果他的組合不夠,請拋出異常。 – Bozho 2010-08-04 06:13:46

+0

在調用構建之前,您可以通過其他方法調用在RequestBuilder構造函數和任何可選參數中傳遞強制參數。多數民衆贊成在建設者:許多可選參數(減少伸縮式構造函數) @bozo你應該真的在建設者構造函數 – atamanroman 2010-08-04 06:16:09

2
interface RequestBuilder { 
    void doStuff(params); 
} 

public RequestBuilder getARequestBuilder() { 
    return new RequestBuilder() { 
    void doStuff(params) { 
     // impl.details 
    } 
    } 
}  

public RequestBuilder getBRequestBuilder() { 
    return new RequestBuilder() { 
    void doStuff(params) { 
     // impl.details 
    } 
    } 
}  

public String buildRequest(yourParams, RequestBuilder builder){ 
    doBefore(); 
    builder.doStuff(yourParams); 
    doAfter(); 
} 

我想,這就是所謂的Strategy模式。它看起來很像Command模式,但是因爲你封裝算法似乎是策略:)

什麼Bozho建議是Builder模式。

我建議你一段時間瀏覽a list of patterns,或者購買Head First Patterns。真的很有趣的閱讀。

+0

我不敢肯定,如果這是一個命令或戰略模式。你解耦一個算法(策略),但另一方面,這顯然是一個封裝的方法調用(命令)。也許有人可以說出爲什麼它的模式。我會說它的命令,但立即調用該方法:) – atamanroman 2010-08-04 06:10:53

+0

@fielding我想這是最重要的意圖。但我只使用模式(有時不知道它是一種模式),我不是一個理論模式的人。 – extraneon 2010-08-04 07:48:12

1

您可以在生成器對象傳遞給通用buildRequest方法。由於不僅算法而且參數也各不相同,所以我把它們放到了構建器中。我不認爲這就是一個很好的解決方案,但我想在這裏展示的命令模式:d(Extraneon展示瞭如何分離PARAMS和命令)

// call somewhere in the code: 
    Builder b = new BTypeBuilder(); 
    b.age = "20"; b.sex = "female"; b.name = "eve"; 
    String res = buildRequest(b); 

    Public String buildRequest(Builder builder) 
    { 
     doSomething(); 
     doMoreStuff(); 
     builder.build(); 
     doAfterStuff(); 
    } 

    // Command pattern 
    class BTypeBuilder implements Builder 
    { 
     String name, age, sex; 

     // Constructor here 

     void build() 
     { 
      // Do your stuff here 
     } 
    } 

    class ATypeBuilder implements Builder 
    { 
     String pin, amount; 

     // Constructor here 

     void build() 
     { 
      // Do your stuff here 
     } 
    } 

    public interface Builder 
    { 
     void build(); 
    } 
+0

我喜歡你的解決方案。但我認爲它將BTypeBuilder()公開給客戶端。這意味着客戶必須瞭解所有不同類型的建設者。這不是「緊密耦合」嗎? – sarahTheButterFly 2010-08-04 00:50:58

+0

你可以引入某種Builder-Factory。靜態工廠方法應該足夠,並隱藏所有不同的構建器。這取決於你在做什麼。如果這是你的公共API的一部分,這個努力是合理的。如果沒有,我不會走得這麼遠。 順便說一句:如果你喜歡答案,upvote它;) – atamanroman 2010-08-04 06:23:00

+0

哈哈......只是upvoted你的文章!謝謝回答我的問題。 ;) – sarahTheButterFly 2010-08-05 03:59:28

0

除了其他的答案,這也可能對您有用(如你只想插件你的方法,不使用你的參數爲「前」和「後」的方法)

interface Function0<R> { 
    R apply(); 
} 

public void performOperation(Function0<Void> operation) { 
    doSomething(); 
    doBeforeStuff(); 
    operation.apply(); 
    doAfterStuff(); 

} 

,那麼你可以使用它像這樣,

final RequestBuilder builder = new RequestBuilder(); 
    performOperation(new Function0<Void>() { 
     public Void apply() { 
      builder.buildATypeRequest("1234", "2445"); 
      return null; 
     } 
    }); 

    performOperation(new Function0<Void>() { 
     public Void apply() { 
      builder.buildBTypeRequest("1234", "2445", "1234"); 
      return null; 
     } 
    }); 
0

,而不是發送一個長PARAM eter列表只是將所有參數推送到地圖中並將該地圖作爲參數發送。

+0

嗯..如果參數列表大小小於6(或4?),那就沒問題。實際上,比我認爲的推動它們更好。用戶如何知道要在地圖上放置什麼? – sarahTheButterFly 2010-08-04 00:53:37

+0

這對什麼有幫助?你必須添加新的驗證,因爲你不能再告訴地圖是否包含擬合對象。引入某種Person類可能更好,它可以將姓名,性別和年齡分組。如果你有很多參數,嘗試引進工廠或建設者。但這與最初的問題無關。 – atamanroman 2010-08-04 06:26:50