生成器模式中的Java类型推断 [英] java type inference in builder pattern

查看:85
本文介绍了生成器模式中的Java类型推断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个参数化的(通用)类 MyType< T> 及其构建器。 builder将具有一些忽略类型 T 的方法和一些使用该类型的方法。但是似乎使用这种模式我必须重复 T 声明:

 如何省略此声明? 
|
V
MyType< String> < String> of()
.method1(argument_can_be_of_any_type)
.method2(argument_must_be_of_type_T =字符串)
.build();

是否可以使用一些Java语法技巧或其他设计模式来省略第二种类型声明并进行API更人性化?例如,

  List< String> aList = Lists.emptyList(); 

  List< String> aList =新的LinkedList<>(); 

我不想在构建器中强制执行任何方法顺序

解决方案

由于我的原始答案无法像宣传的那样工作,因此我做了一些重做。 (感谢shmosel发现问题,并感谢Daniel Pryden提供建议的解决方案。)

  / * Box.java的内容* / 
公共类Box< T>
{
私人T内容;
个私有对象数据;

受保护的Box(T内容,对象数据){
this.contents =内容;
this.data =数据;
}

public static BoxBuilder builder(){
return new BoxBuilder();
}

public T getContents(){
返回内容;
}
}

/ * BoxBuilder.java的内容* /
公共类BoxBuilder
{
私有对象数据;

public BoxBuilder withAnything(Object o){
this.data = o;
返回;
}

//从参数
public< T>推断新类型TypedBoxBuilder< T> withBoxContent(T contents){
TypedBoxBuilder< T> builder =新的TypedBoxBuilder< T>();
builder.setData(data);
builder.setContents(contents);

退货建造者;
}
}

/ * TypedBoxBuilder.java的内容* /
公共类TypedBoxBuilder< T>
{
私人T内容;
个私有对象数据;

public TypedBoxBuilder(){
}

public TypedBoxBuilder< T> withAnything(Object data){
this.data = data;
返回;
}

public TypedBoxBuilder< T> withContents(T contents){
this.contents = contents;
返回;
}

public Box< T> build(){
返回新Box< T>(内容,数据);
}

public void setContents(T contents){
this.contents = contents;
}

public void setData(Object data){
this.data = data;
}
}

这是客户端代码:

  Box< String> box = Box.builder()//返回BoxBuilder 
.withBoxContent( FOO)//返回TypedBoxBuilder< String>
.withAnything(42)//返回TypedBoxBuilder< String>
.build(); //返回Box< String>
字符串c = box.getContents();

这也有效:

  Box< String> box = Box.builder()//返回BoxBuilder 
.withAnything(42)//返回BoxBuilder
.withBoxContent( FOO)//返回TypedBoxBuilder< String>
.build(); //返回Box< String>
字符串c = box.getContents();


i want to create a parameterized (generic) class MyType<T> and its builder. builder will have some methods that ignore the type T and some methods that use the type. but it seems like using this pattern i have to repeat the T declaration:

                     how to omit this declaration?
                                   |
                                   V
MyType<String> myType = Builder.<String>of()
                               .method1(argument_can_be_of_any_type)
                               .method2(argument_must_be_of_type_T = String)
                               .build();

is it possible to use some java syntax tricks or other design patterns to omit the second type declaration and make the API more user friendly? like for example:

List<String> aList = Lists.emptyList();

or

List<String> aList = new LinkedList<>();   

i don't want to enforce any order of methods in the builder

解决方案

I've reworked things a bit since my original answer didn't work as advertised. (Thanks to shmosel for spotting the problem, and to Daniel Pryden for the suggested solution.)

/* contents of Box.java */
public class Box<T>
{
    private T contents;
    private Object data;

    protected Box(T contents, Object data) {
        this.contents = contents;
        this.data = data;
    }

    public static BoxBuilder builder() {
        return new BoxBuilder();
    }

    public T getContents() {
        return contents;
    }
}

/* contents of BoxBuilder.java */
public class BoxBuilder
{
    private Object data;

    public BoxBuilder withAnything(Object o) {
        this.data = o;
        return this;
    }

    // Infers new type from argument
    public <T> TypedBoxBuilder<T> withBoxContent(T contents) {
        TypedBoxBuilder<T> builder = new TypedBoxBuilder<T>();
        builder.setData(data);
        builder.setContents(contents);

        return builder;
    }
}

/* contents of TypedBoxBuilder.java */
public class TypedBoxBuilder<T>
{
    private T contents;
    private Object data;

    public TypedBoxBuilder() {
    }

    public TypedBoxBuilder<T> withAnything(Object data) {
        this.data = data;
        return this;
    }

    public TypedBoxBuilder<T> withContents(T contents) {
        this.contents = contents;
        return this;
    }

    public Box<T> build() {
        return new Box<T>(contents, data);
    }

    public void setContents(T contents) {
        this.contents = contents;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

And here's the client code:

Box<String> box = Box.builder() // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .withAnything(42) // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();

And this works as well:

Box<String> box = Box.builder() // Returns BoxBuilder
        .withAnything(42) // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();

这篇关于生成器模式中的Java类型推断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆