2014-09-23 2 views
6

У меня есть несколько разных POJOs, которые используют builder pattern, но после добавления построителя для каждого из них и создания Object.toString, Object.hashCode и Object.equals, мои классы заканчиваются примерно на 100 строк кода. Должен быть лучший способ справиться с этим. Я думаю, что иметь какой-то отражающий строитель поможет много, но я не уверен, что это будет хорошая практика, и я также не уверен, как именно это произойдет. Другими словами, есть ли способ реализовать такой конструктор?Слишком много шаблонов, как я могу уменьшить свои строители POJO?

Простой POJO:

public class Foo { 

    public int id; 
    public String title; 
    public boolean change; 
    ... 

} 

Тогда какой-то светоотражающие строитель:

Foo = ReflectiveBuilder.from(Foo.class).id(1).title("title").change(false).build(); 
+0

Используете ли вы общие ресурсы Apache для hashCode toString и равно? Это все еще боль, но сэкономит вам много времени. У вас есть базовый класс, который рефлексивно делает toString, equals и hashCode, а затем выводит все ваши POJO из этого – Leon

+0

@Leon. На самом деле. Но каждый класс по-прежнему будет составлять 70-100 строк кода от каждого строителя.Должна быть лучшая модель, о которой я просто не знаю, или способ реализовать отражающий строитель, по крайней мере, так я себя чувствую. – buildpattern

ответ

4

Короткий ответ нет. То, о чем вы просите, невозможно. Reflection рассматривает код во время выполнения и динамически вызывает методы, он не может генерировать фактические методы.

Что вы могли бы сделать:

Foo foo = ReflectiveBuilder.from(Foo.class). 
       set("id", 1). 
       set("title", "title"). 
       build(); 

Это имеет три массовые проблемы:

  1. поля являются String s - опечатка приводит к ошибке во время выполнения, а не компиляции одного ,
  2. значения Object s - неправильный тип вызывает ошибку времени выполнения, а не время компиляции, и
  3. было бы намного медленнее, чем альтернатива, так как отражение очень медленное.

Таким образом, решение на основе отражения, хотя и возможно (см. Apache Commons BeanUtils BeanMap), совсем не практично.

Долгий ответ, если вы готовы разрешить некоторые магии времени компиляции, вы можете использовать Project Lombok. Идея Lombok заключается в создании кода шаблона из аннотаций с использованием препроцессора аннотации Java.

Действительно волшебная вещь заключается в том, что все IDE, а также большие 3, по крайней мере, понимают, что предварительная обработка аннотаций и завершение кода будут функционировать корректно, даже если код не действительно существует.

В случае включения POJO с Builder вы можете использовать @Data и @Builder

@Data 
@Builder 
public class Foo { 

    public int id; 
    public String title; 
    public boolean change; 
    ... 

} 

@Data аннотацию сгенерирует:

  • необходимым аргументы конструктора (который принимает все final поля),
  • equals и hashCode методы, которые используют все поля (может быть сконфигурирован с @EqualsAndHashCode аннотацию)
  • toString метод на всех областях (могут быть сконфигурированы с @ToString аннотацию и
  • public методы получения и установки для всех полей (могут быть сконфигурированы с использованием @Getter/@Setter аннотации на полях).

@Builder аннотации будут генерировать внутренний класс под названием Builder, которые могут быть инстанцированным с помощью Foo.builder().

ли убедитесь, что вы настроить методы equals, hashCode и toString, как если у вас есть два класса с Ломбками, которые имеют ссылки друг на друг, то вы будете в конечном итоге с бесконечным циклом в случае, если по умолчанию, как оба класса включает другие в эти методы.

Существует также новый configuration system, что позволяет использовать, например, текучие сеттер, так что вы можете более или менее покончите с застройщиком, если ваш POJO изменчив:

new Foo().setId(3).setTitle("title)... 

Для другого подхода, можно посмотрите на Aspect-oriented programming (АОП) и AspectJ. AOP позволяет вам рубить ваши классы в «аспекты», а затем придерживаться их вместе с помощью определенных правил с использованием предварительного компилятора. Например, вы можете точно реализовать то, что делает Lombok, используя пользовательские аннотации и аспект. Однако это довольно сложная тема, и ее вполне можно переусердствовать.

+0

Я понял, что 'Gson' фактически использует очень похожий подход для десериализации« Object », поскольку он использует отражение для инициализации каждого« поля ». Конструктор, основанный на одной и той же реализации отражения, может быть не такой плохой идеей. Как вы думаете? – buildpattern

+1

@buildpattern Это ужасная идея, как я указываю. GSON делает это, потому что это _has_ to. Вы теряете безопасность типа времени компиляции, а это означает, что вы можете ударить по ошибкам во время выполнения, и вы теряете скорость. Не используйте рефлексию, если вы не ** ** ** не должны, и ** никогда не **, чтобы уменьшить шаблон. –

4

Может Project Lombok (да сайт некрасиво) является вариантом для вас. Ломбок вводит код в ваши классы на основе аннотаций.

С Ломбок вы используете @Data аннотаций сгенерированных добытчиками, сеттеров, toString(), hashCode() и equals():

@Data 
public class Foo { 
    public int id; 
    public String title; 
    public boolean change; 
} 

Посмотрите на пример на @Data documentation section, чтобы увидеть сгенерированный код.

Lombok также предоставляет @Builder, который создает строитель для вашего класса. Но следует помнить, что это экспериментальная функция:

@Builder 
public class Foo { 
    public int id; 
    public String title; 
    public boolean change; 
} 

Теперь вы можете сделать:

Foo foo = Foo.builder() 
    .id(123) 
    .title("some title") 
    .change(true) 
    .build(); 
0

Я создал небольшую библиотеку CakeMold, чтобы свободно выполнять инициализацию POJO. Он использует отражение, что, конечно, не быстро. Но может быть очень полезно, когда нужно писать тесты.

Person person = CakeMold.of(Person.class) 
    .set("firstName", "Bob") 
    .set("lastName", "SquarePants") 
    .set("email", "[email protected]") 
    .set("age", 22) 
    .cook(); 
1

Я лично использую this сайт, чтобы создать все шаблонный код для POJOs для меня. Все, что вам нужно сделать, это вставить JSON, который вы хотите проанализировать, и он будет генерировать все классы для вас. Затем я просто использую Retrofit для выполнения запросов/кэширования/анализа информации. Here - пример Модернизации и POJO в моей учетной записи Github. Надеюсь, это поможет!

Смежные вопросы