2010-08-03 10 views
5

Ich habe eine Klasse enthält 10 Methoden, die fast die gleichen Dinge tun, abgesehen von einem Schlüsselereignis. Zwei Beispiele sind unten angegeben:entfernen Duplikation


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(); 
} 
 

Wie Sie aus den oben genannten Methoden sehen können, sind sie auseinander ähnlich der Aufruf von verschiedenen Methoden zur Verfügung gestellt von requestBuilder. Die restlichen 8 sind auch ähnlich. Es gibt viel doppelten Code hier. Ich denke, es gibt einen besseren Weg, dies zu implementieren, aber ich weiß nicht wie. Irgendwelche Ideen und Vorschläge werden geschätzt.

Danke, Sarah

+1

Wird Ihre Anfrage tatsächlich in der Methode verwendet? – helpermethod

+0

@Helper Ja, ist es. Sie können sagen, dass es in doAfterSuff() verwendet wird; – sarahTheButterFly

Antwort

5

Verwendung so etwas wie RequestBuilder, die alle diese Arten von Parametern akzeptiert:

public RequestBuilder { 
    // setters and getters for all properties 

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

und dann

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

Ich habe eine Frage hier. Wenn ein Client, der den RequestBuilder() verwendet, weiß er, welche Parameter er einstellen soll? Nehmen Sie die zwei Methoden in meinem Beitrag zum Beispiel, ich würde den Klienten bitten müssen, zu wählen, um 2 der 5 möglichen Parameter zu setzen. Wie können wir sicher sein, dass der Client keinen falschen Parameter setzt? – sarahTheButterFly

+0

es setzt, was auch immer es will (hat 'zur Hand'). Wenn die Kombination nicht ausreicht, werfen Sie eine Ausnahme aus. – Bozho

+0

Sie übergeben die obligatorischen Parameter im RequestBuilder-Konstruktor und alle optionalen Parameter vor dem Aufruf von build durch zusätzliche Methodenaufrufe. Das ist, wofür der Erbauer gemacht ist: viele optionale Parameter (um Teleskopkonstrukteure zu reduzieren) @bozo sollten Sie wirklich die obligatorischen Parameter im Erbauer – atamanroman

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(); 
} 

Ich denke, das das Strategy Muster genannt wird. Es sieht sehr ähnlich dem Command Muster aus, aber weil Sie einen Algorithmus kapseln, scheint es Strategie zu sein :)

Was Bozho vorschlagen, ist das Builder Muster.

Ich empfehle Ihnen, durch a list of patterns einige Zeit zu durchsuchen, oder kaufen Head First Patterns. Wirklich Spaß beim Lesen.

+0

Ich war nicht sicher, ob dies ein Befehl oder ein Strategie-Muster war. Dein Entkoppeln ist zwar ein Algo (Strategie) aber auf der anderen Seite ist dies eindeutig ein gekapselter Methodenaufruf (Befehl). Vielleicht kann jemand sagen, warum welches Muster es ist. Ich würde seinen Befehl sagen, obwohl die Methode sofort aufgerufen wird :) – atamanroman

+0

@fielding Ich denke, es ist die Absicht, die am wichtigsten ist. Aber ich benutze nur Muster (manchmal ohne zu wissen, dass es ein Muster ist :) und ich bin kein theoretischer Mustertyp. – extraneon

1

Sie konnten die Erbauer Objekt zu einem allgemeinen buildRequest-Methode übergeben. Da nicht nur der Algorithmus, sondern auch die Argumente variieren, lege ich sie in den Builder. Ich denke nicht, das ist eine schöne Lösung, aber ich wollte hier ein Befehlsmuster zeigen: D (Extraneon zeigte, wie params und Befehl zu entkoppeln)

// 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

Ich mag deine Lösung. Aber ich denke, dass es die BTypeBuilder() einem Client zur Verfügung stellt. Das bedeutet, dass der Kunde über die verschiedenen Arten von Bauarbeitern Bescheid wissen muss. Ist das nicht "enge Kopplung"? – sarahTheButterFly

+0

Sie könnten eine Art Builder-Factory einführen. Eine statische Factory-Methode sollte ausreichen und alle verschiedenen Builder verbergen. Es hängt davon ab, was Sie tun. Wenn dies Teil Ihrer öffentlichen API ist, ist der Aufwand sinnvoll. Wenn nicht, würde ich nicht so weit gehen. BTW: Wenn Sie eine Antwort mögen, upvote es;) – atamanroman

+0

Haha ... hat gerade Ihren Beitrag upvoted! Danke, dass du meine Frage beantwortet hast. ;) – sarahTheButterFly

0

Neben anderen Antworten, könnte dies auch für Sie nützlich sein (If Sie wollen einfach nur Ihre Methode Plugin, nicht Ihre Parameter für die ‚vor‘ und ‚nach‘ Methoden)

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

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

} 

dann könnte man es so mit verwenden,

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

Anstatt eine lange param senden In der Liste drücken Sie einfach alle Parameter in einer Karte und senden diese Karte als Argument.

+0

Hmmm..Wenn die Parameterliste kleiner ist als 6 (oder 4?), Dann ist es ok. Eigentlich besser, als sie in eine Karte zu schieben, denke ich. Woher weiß Ihr Benutzer, was er in die Karte einfügen soll? – sarahTheButterFly

+0

Wo hilft das etwas? Sie müssen eine neue Validierung hinzufügen, da Sie nicht mehr sagen können, ob die Karte passende Objekte enthält. Es wäre besser, irgendeine Art von Personenklasse einzuführen, die den Namen, das Geschlecht und das Alter gruppieren könnte. Wenn Sie viele Params haben, versuchen Sie, Fabriken oder Bauherren einzuführen. Aber das hat nichts mit der Ausgangsfrage zu tun. – atamanroman

Verwandte Themen