2013-08-07 9 views
5

Ich versuche, ein Builder-Muster zu erstellen, das Generics verwendet, um eine Typüberprüfung für einige der Methoden bereitzustellen. Zur Zeit habe ich folgende Arbeiten:Generische Art von Enum & Builder-Muster

ParameterBuilder.start(String.class).setName("foo").setDefaultValue("Hello").build(); 
ParameterBuilder.start(Integer.class).setName(bar).setDefaultValue(42).build(); 
ParameterBuilder.start(Boolean.class).setName(bar).setDefaultValue(false).build(); 

mit dem Code:

public class ParameterBuilder<T> { 
    private String name; 
    private T defaultValue; 

    public static <T2> ParameterBuilder<T2> start(Class<T2> type) { 
    return new ParameterBuilder<T2>(); 
    } 
    // Other methods excluded for example 
} 

So ist die Art der Eingabe für die setDefaultValue Methode wird definiert durch das, was in die start Methode übergeben wird, so wie ich will.

Aber jetzt möchte ich erweitern, was in start() übergeben wird, um ein wenig mehr Informationen zu enthalten. Im Wesentlichen möchte ich einen "Typ" für die Parameter, die ich erstelle, übergeben. Manchmal werden diese Parameter Dinge wie „E-Mail“, „url“ usw. Der Standardwert nach wie vor von einer bekannten Art sein wird (String) in denjenigen Fällen, so möchte ich etwas haben, wie:

ParameterBuilder.start(EMAIL).setName("email").setDefaultValue("[email protected]").build(); 
ParameterBuilder.start(URL).setName("website").setDefaultValue("http://www.somewhere.com").build(); 

Wo im Moment EMAIL & URL enums sind, enthält unter anderem - die Klasse des Vorschlagswerts. Aber wenn ich diesen Weg gehen würde, wie würde ich den Parameter Builder instanziieren?

public static <T2> ParameterBuilder<T2> start(ParameterType paramType) { 
    Class<T2> type = paramType.getTypeClass(); 
    // How do I instantiate my ParameterBuilder with the right type? 
} 

Wenn es nicht mit Aufzählungen getan werden kann (was ich der Fall sehen kann), hat jemand einen Vorschlag für eine andere Lösung?

+1

Können Sie zeigen, was genau ist 'EMAIL',' URL'. Sind das 2 verschiedene Enums? Sind das Instanzen von zwei enums? Was sind Sie? –

+0

In meinem Fall hatte ich eine ParameterType, die so etwas wie: public enum ParameterType {STRING (String.class, "String"), INTEGER (Integer.class, "Integer"), MULTILINE (String.class, "Multite Text")), HTML (String.class, "HTML"), DATUM (Date.class, "Date"), BOOLEAN (Boolean.class, "Boolean"); // Methoden folgen " –

Antwort

2

Ich denke, dass Sie eine enum pro Klassenart benötigen (ich sehe nicht, wie Sie eine enum Abdeckung mehrere Typen haben könnten und halten Sie das Ding arbeiten). In diesem Fall könnte eine allgemeine generische Schnittstelle tun, was Sie wollen. Sie können dann eine Art Fabrik erstellen, um die Enum-Konstanten zur Verfügung zu stellen, wenn das hilft.

Dies kompiliert:

static interface ParameterType<T> {} 

static enum ParameterTypeEnum implements ParameterType<String> { EMAIL; } 

public static void main(String[] args) { 
    ParameterBuilder 
      .start(ParameterTypeEnum.EMAIL) 
      .setName("email") 
      .setDefaultValue("[email protected]") 
      .build(); 
} 

public static class ParameterBuilder<T> { 

    private String name; 
    private T defaultValue; 

    public static <T2> ParameterBuilder<T2> start(ParameterType<T2> paramType) { 
     return new ParameterBuilder<T2>(); 
    } 

    ParameterBuilder<T> setName(String name) { 
     this.name = name; 
     return this; 
    } 

    ParameterBuilder<T> setDefaultValue(T defaultValue) { 
     this.defaultValue = defaultValue; 
     return this; 
    } 

    void build() {} 
} 
+0

Das hört sich nach einer vernünftigen Methode an. Auf diese Weise könnte ich StringParameterEnum, IntegerParameterEnum usw. haben, wodurch der Code immer noch sauber bleibt. Vielen Dank –

0

Ich bin nicht sicher, den Kontext in dem, was Sie verwenden möchten, aber ich denke, das folgende könnte eine Option sein.

Sie können dem Open/Closed-Prinzip folgen und eine Schnittstelle Parameter erstellen und eine Implementierung pro Typ haben. Der Vorteil davon ist, dass Sie keinen neuen Enum-Wert für jeden neuen Parameter hinzufügen müssen. Sie können später die Klasse ParameterBuilder anstelle der Enum übergeben und die ParameterBuilder und Parameter würden zusammenarbeiten, um zu bauen, was Sie brauchen.

So könnte ParameterBuilder.start() eine Instanz der spezifischen Parameter zurückgeben und der Parameter könnte verschiedene Methoden abhängig von der Art des Parameters haben.

Ich denke nicht, dass diese Antwort wirklich gut ist, aber hoffentlich kann sie Ihnen einen Hinweis geben, wie Sie eine mögliche Lösung für Ihren Kontext erstellen können.

0

Sie könnten ein Objekt hierachie für diese E-Mail und URL-Typen

public class DefaultType { 
    protected String name; 
    protected String defaultValue; 
    //some constructor 
} 

public class EmailType extends DefaultType { 
    ... 
} 

public class URLType extends DefaultType { 
    ... 
} 

dann der Parameter Builder wie folgt aussehen könnte erstellen:

public static ParameterBuilder start(DefaultType type) { 
    ParameterBuilder builder = new ParameterBuilder(type); 
    builder.setType(type); 
    return builder; 
} 

Dann sind Sie es so nennen könnte:

ParameterBuilder.start(new EmailType("name","value");... 

hilft Ihnen das oder wollen Sie nicht in diese Richtung gehen?

Verwandte Themen