来自Enum的通用类型& Builder模式

时间:2013-08-07 10:29:10

标签: java generics type-erasure

我正在尝试创建一个构建器模式,该模式使用泛型来提供某些方法的类型检查。目前我的工作如下:

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

使用代码:

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
}

因此,setDefaultValue方法的输入类型由传递到start方法的内容定义,就像我想要的那样。

但现在我想扩展传递给start()的内容以包含更多信息。基本上我想传入&#34;类型&#34;对于我创建的参数。有时这些参数会像&#34; email&#34;,&#34; url&#34;默认值仍然是已知类型(在这种情况下为String),所以我希望有类似的东西:

ParameterBuilder.start(EMAIL).setName("email").setDefaultValue("foo@bar.com").build();
ParameterBuilder.start(URL).setName("website").setDefaultValue("http://www.somewhere.com").build();

目前EMAIL&amp; URL是枚举,包含其他内容 - 默认值的类。但是,如果我沿着这条路走下去,我将如何实例化参数构建器?

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

如果不能使用枚举(我可以看到这种情况),是否有人建议使用其他解决方案?

3 个答案:

答案 0 :(得分:2)

我认为你需要每个类类型一个枚举(我不知道如何让一个枚举覆盖几种类型并保持工作)。在这种情况下,一个通用的通用接口可以做你想要的。然后,您可以创建某种工厂以提供枚举常量(如果有帮助的话)。

编译:

static interface ParameterType<T> {}

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

public static void main(String[] args) {
    ParameterBuilder
           .start(ParameterTypeEnum.EMAIL)
           .setName("email")
           .setDefaultValue("foo@bar.com")
           .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() {}
}

答案 1 :(得分:0)

我不确定你想要使用它的上下文,但我认为以下可能是一个选项。

您可以遵循开放/封闭原则并创建一个接口Parameter,每种类型都有一个实现。这样做的好处是,您不需要为所需的每个新参数添加新的枚举值。您可以稍后将课程传递给ParameterBuilder而不是枚举,而ParameterBuilderParameter将共同构建您需要的内容。

因此ParameterBuilder.start()可以返回特定Parameter的实例,参数可能有不同的方法,具体取决于参数的类型。

我不认为这个答案真的很好,但希望能给你一个如何为你的背景建立潜在解决方案的暗示。

答案 2 :(得分:0)

您可以为这些电子邮件和网址类型

创建对象层次结构
public class DefaultType {
    protected String name;
    protected String defaultValue;
    //some constructor
}

public class EmailType extends DefaultType {
    ...
}

public class URLType extends DefaultType {
    ...
}

然后参数构建器可能如下所示:

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

然后你可以这样称呼它:

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

这有帮助,或者你不想朝这个方向前进?