Почему я не должен использовать неизменяемые POJO вместо JavaBeans? - PullRequest
77 голосов
/ 18 августа 2010

Я реализовал несколько приложений Java сейчас, пока только настольные приложения.Я предпочитаю использовать неизменяемые объекты для передачи данных в приложении вместо использования объектов с мутаторами (setters и getters ), также называемыми JavaBeans.

Но в мире Java это кажетсягораздо чаще использовать JavaBeans, и я не могу понять, почему я должен использовать их вместо этого.Лично код выглядит лучше, если он работает только с неизменяемыми объектами, а не постоянно изменяет состояние.

Неизменяемые объекты также рекомендуются в Элемент 15: Минимизировать изменчивость , Эффективная Java 2ed .

Если у меня есть объект Person, реализованный как JavaBean это будет выглядеть так:

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

И тот же Person реализован как неизменяемый объект:

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Илиближе к struct в C:

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

Я мог бы также иметь геттеры в неизменяемом объекте, чтобы скрыть детали реализации.Но поскольку я использую его только как struct, я предпочитаю пропускать «получатели» и сохранять его простым.

Проще говоря, я не понимаю, почему лучше использовать JavaBeans, или если я могу иследует продолжать работу с моими неизменяемыми POJO?

Многие из библиотек Java, похоже, лучше поддерживают JavaBeans, но, возможно, со временем становится все более популярной поддержка неизменяемых POJO?

Ответы [ 6 ]

76 голосов
/ 18 августа 2010

Предпочитать JavaBeans Когда

  • вам нужно взаимодействовать со средами, которые ожидают их
  • , у вас есть множество свойств, для которых было бы неудобно выполнять всю инициализацию при создании экземпляра
  • у вас есть состояние, которое по какой-то причине дорого или невозможно скопировать, но требует мутации
  • вы думаете, что в какой-то момент вам, возможно, придется изменить способ доступа к свойствам (например, переход от сохраненных к вычисленным значениям, авторизация доступаи т. д.)
  • вы хотите соответствовать стандартам кодирования, которые бездумно настаивают на том, что как-то более «объектно-ориентировано» использовать JavaBeans

Предпочитать неизменяемые POJO при

  • у вас есть небольшое количество простых свойств
  • вам не нужно взаимодействовать со средами, предполагая соглашения JavaBean
  • легко (или по крайней мере возможно) копировать состояние, когдаклонируя ваш объект
  • вы вообще не планируете клонировать объект
  • вы почти увереныЕсли вам не нужно изменять способ доступа к свойствам, как указано выше
  • , вы не против слушать нытье (или насмешку) о том, что ваш код недостаточно "объектно-ориентирован"
38 голосов
/ 18 августа 2010

Я был удивлен, что слово Thread нигде не фигурировало в этом обсуждении.

Одним из основных преимуществ неизменяемых классов является то, что они по своей природе более поточно-безопасны из-за отсутствия изменяемого, совместно используемое состояние.

Это не только упрощает кодирование, но и дает два дополнительных преимущества в качестве побочного эффекта:

  • Меньше необходимости в синхронизации.

  • Больше возможностей для использования конечных переменных, что может облегчить последующую оптимизацию компилятора.

Я действительно пытаюсь перейти к неизменным объектам, а не к классам в стиле JavaBean.Разоблачение кишок объектов с помощью методов получения и установки, вероятно, не должно быть выбором по умолчанию.

16 голосов
/ 18 августа 2010

Ну, это зависит от того, что вы пытаетесь сделать. Если вы работаете с постоянным слоем, и вы извлекаете какую-то строку из базы данных в POJO, и вы хотите изменить свойство и сохранить его обратно, лучше использовать стиль JavaBean, особенно если у вас много свойств.

Учтите, что у вашего человека много полей, таких как: имя, отчество, фамилия, дата рождения, члены семьи, образование, работа, зарплата и т. Д.

И этот Человек оказывается женщиной, которая только что вышла замуж и согласилась изменить свою фамилию, и вам необходимо обновить базу данных.

Если вы используете неизменный POJO, вы выбираете объект Person, представляющий ее, затем вы создаете новый объект Person, которому вы передаете все свойства, которые вы не изменили, как они есть, и новую фамилию, и сохрани это.

Если бы это был Java-бин, вы можете просто сделать setLastName () и сохранить его.

Это «Минимизируйте изменчивость», а не «никогда не используйте изменяемые объекты». Некоторые ситуации лучше работают с изменяемыми объектами, и ваша задача - решить, подойдет ли изменяемый объект к вашей программе или нет. Вы не должны всегда говорить «должны использовать неизменяемые объекты», вместо этого посмотрите, сколько классов вы можете сделать неизменяемыми, прежде чем начать причинять себе вред.

7 голосов
/ 18 августа 2010

Обобщая другие ответы, я думаю, что:

  • Неизменность способствует правильности (структуры могут быть переданы по ссылке, и вы знаете, что ничего не будет уничтожено неисправным / злонамеренным клиентом) ипростота кода
  • Изменчивость облегчает однородность : Spring и другие платформы создают объект без аргументов, задают свойства объекта и voi là .Также упростите интерфейсы, используя один и тот же класс для предоставления данных и сохранения изменений (вам не нужны get(id): Client и save(MutableClient), так как MutableClient является потомком клиента.

Если существует промежуточная точка(создавать, устанавливать свойства, делать неизменяемыми), может быть, фреймворки будут поощрять более неизменный подход.

В любом случае я предлагаю думать о неизменяемых объектах как о «только для чтения Java-бинах», подчеркивая тот факт, что если вы хороший пареньне трогайте этот опасный метод setProperty все будет хорошо.

3 голосов
/ 23 сентября 2014

С Java 7 вы можете иметь неизменные бины, лучшие из двух миров. Используйте аннотацию @ConstructorProperties в своем конструкторе.

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}
2 голосов
/ 18 августа 2010

Не думаю, что неизменные объекты станут такими популярными, если честно.

Я вижу преимущества, но фреймворки, такие как Hibernate и Spring, в настоящее время очень популярны (и не без причины), и они действительно лучше всего работают с бобами.

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

РЕДАКТИРОВАТЬ Комментарии побуждают меня уточнить мой ответ.

Скорее всего, существуют проблемные области, в которых неизменность очень полезна и действительно используется. Но я думаю, что текущее значение по умолчанию кажется изменчивым, поскольку это то, что в основном ожидается, и только неизменным, если оно имеет явное преимущество.

И хотя в Spring действительно возможно использовать конструкторы с аргументами, похоже, что он предназначен для использования устаревшего и / или стороннего кода с вашим прекрасным новым кодом Spring. По крайней мере, это то, что я взял из документации.

...