Подтвердить что ты не робот

Генераторы Java + шаблон Builder

Как мне позвонить start() ниже?

package com.example.test;

class Bar {}

public class Foo<K>
{
    final private int count;
    final private K key;

    Foo(Builder<K> b)
    {
        this.count = b.count;
        this.key = b.key;
    }

    public static class Builder<K2>
    {
        int count;
        K2 key;

        private Builder() {}
        static public <K3> Builder<K3> start() { return new Builder<K3>(); }
        public Builder<K2> setCount(int count) { this.count = count; return this; }
        public Builder<K2> setKey(K2 key) { this.key = key; return this; }
        public Foo<K2> build() { return new Foo(this); }
    }

    public static void main(String[] args)
    {
        Bar bar = new Bar();
        Foo<Bar> foo1 = Foo.Builder.start().setCount(1).setKey(bar).build();
        // Type mismatch: cannot convert from Foo<Object> to Foo<Bar>

        Foo<Bar> foo2 = Foo.Builder<Bar>.start().setCount(1).setKey(bar).build();
        // Multiple markers at this line
        // - Bar cannot be resolved
        // - Foo.Builder cannot be resolved
        // - Syntax error on token ".", delete this token
        // - The method start() is undefined for the type Foo<K>
        // - Duplicate local variable fooType mismatch: cannot convert from Foo<Object> to Foo<Bar>

        Foo<Bar> foo3 = Foo<Bar>.Builder.start().setCount(1).setKey(bar).build();
        // Multiple markers at this line
        // - Foo cannot be resolved
        // - Syntax error on token ".", delete this token
        // - Bar cannot be resolved     
    }
}
4b9b3361

Ответ 1

Вы были близки:

Foo.Builder.<Bar> start().setCount(1).setKey(bar).build();

Ура!:)

P.S. Если компилятор не может вывести параметр типа метода самостоятельно, вы можете принудительно его вызвать, вызвав obj.<Type> method(...).

P.P.S вы можете использовать:

public Foo<K2> build() {
    return new Foo<K2>(this);
}

Избегайте использования необработанных типов.

Ответ 2

Метод Андрея в порядке, но большинство программистов, вероятно, будут бороться с довольно неизвестным синтаксисом. Это может быть проще использовать следующим образом:

static public <K3> Builder<K3> start(Class<K3> cls) { return new Builder<K3>(); }

Foo<Bar> foo1 = Foo.Builder.start(Bar.class).setCount(1).setKey(bar).build();

Класс передается только для помощи с общим типом. Это не очень, но, по крайней мере, синтаксис является общеизвестным.

Другой вариант - сразу начать с объекта общего типа:

Foo<Bar> foo1 = Foo.Builder.startWithKey(bar).setCount(1).build();

Ответ 3

Это моя реализация шаблона generic builder в java 8.

    public class Builder<T> {
    private T instance;
    private boolean ifCond = true; // default
    public Builder(Class<T> clazz){
       try {
           instance = clazz.newInstance();
       } catch (InstantiationException | IllegalAccessException e) {
           e.printStackTrace();
       } 
    }

    public Builder<T> with(Consumer<T> setter){
       if(ifCond)
           setter.accept(instance);
       return this;
    }

    public T get(){
       return instance;
    }

    public static <T> Builder<T> build(Class<T> clazz) {
       return new Builder<>(clazz);
    }

    public Builder<T> If(BooleanSupplier condition){
       this.ifCond = condition.getAsBoolean();
       return this;
    }

    public Builder<T> endIf(){
        this.ifCond = true;
        return this;
    }
 }

How to use it:

List list = Arrays.asList(1, 2, 3, 4, 5)

System.out.println(
   Builder.build(Sample.class)
          .with(s -> s.setId(1))
          .with(s -> s.setName("Sample object"))
          .with(s -> s.setList(list))
          .get()
);

// Java Properties
System.out.println(
   Builder.build(Properties.class)
          .with(p -> p.put("one", 1))
          .with(p -> p.put("two", 2))
          ...
          .get()

);
System.out.println(Builder.build(Properties.class)
                  .with(p -> p.put("one", 1))
                  .If(() -> false) // any expression return boolean
                  .with(p -> p.put("two", 2))
                  .with(p -> p.put("three", 3))
                  .endIf()
                  .with(p -> p.put("four", 4))
                  .get()

 ); // output=> {one=1, four=4}

https://howtocodetutorial.wordpress.com/generic-builder-pattern-in-java-8/