Создание неизменных объектов из javabean - PullRequest
5 голосов
/ 15 апреля 2009

Я участвую в этом проекте, в котором мы опираемся на унаследованный код. У меня есть особая ситуация с одним большим объектом Java-бина, который должен быть передан по проводам. Поэтому моей первой мыслью было сделать его неизменным и сериализуемым, чтобы выполнить трюк. На этом этапе я столкнулся с несколькими трудными выборами:

  1. В идеале я хочу какой-то способ автоматически генерировать неизменяемый, Сериализуемая версия этого класса. У меня нет возможности рефакторинга или изменить этот класс в любом случае, и я действительно очень не хотелось бы скопировать вставить класс с другое имя?

  2. Предполагая, что я отказался от 1, т.е. на самом деле решили дублировать код ОГРОМНЫЙ класс javabean, я все еще будет в сомнительной ситуации о необходимости написать конструктор с 20-25 параметрами, чтобы сделать этот класс неизменен. что такое лучший способ сделать класс неизменным кроме инъекции в конструктор?

Спасибо и всего наилучшего,

Ответы [ 6 ]

4 голосов
/ 25 марта 2010

«Эффективная Java» Джошуа Блоха иллюстрирует шаблон Builder, где простые объекты Builder используются для создания сложного объекта с длинным списком аргументов конструктора. Я бы порекомендовал это.

http://www.drdobbs.com/java/208403883;jsessionid=PJWS41F5DJ4QRQE1GHRSKH4ATMY32JVN?pgno=2

4 голосов
/ 16 апреля 2009

Чтобы сделать его действительно неизменным, вам нужно инициализировать элементы во время строительства.

Один из способов (и я не говорю, что это красиво!) Сделать это и избежать огромного списка параметров в конструкторе - это иметь изменяемый тип с такими же свойствами. Задайте свойства изменяемого типа по одному через «установщики», затем передайте изменяемый объект конструктору неизменяемого типа в качестве единственного аргумента. Затем неизменный объект копирует свойства из изменяемого источника в свои собственные (final) члены.

Вы также можете рассмотреть «эффективную неизменность». То есть, несмотря на то, что неизменность не обеспечивается системой, вы используете методы кодирования, которые четко отделяют фазу инициализации от фазы использования. Ведь неизменяемость не требуется для сериализации.

Вы можете сделать еще один шаг, создав оболочку, скрывающую реализацию, для интерфейса, который не раскрывает свойства реализации. Оболочка реализует только методы в интерфейсе, делегируя «реальную» реализацию. Установщики и получатели из реализации отсутствуют в оболочке. Это предотвратит простое приведение клиентов от интерфейса к классу реализации и манипулирование свойствами.

1 голос
/ 25 марта 2010

А как насчет простого интерфейса только для чтения, охватывающего геттеры?

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

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

1 голос
/ 16 апреля 2009

20-25 свойств невелики, особенно если вы используете полуприличный редактор.

Если у вас уже есть изменяемый экземпляр при создании неизменяемой версии, просто передайте его конструктору.

Если вы хотите быть действительно злым хакером , используйте java.beans для создания сериализуемого Map для изменяемого класса или подкласса, реализующего Externalizable. В качестве альтернативы вы можете использовать java.beans XML-сериализацию (XML, который можно отправить через Java-сериализацию ...).

0 голосов
/ 16 апреля 2009

Несколько идей:

Защищенные сеттеры и заводские методы Вы можете определить bean-компоненты с помощью защищенных методов установки и в том же пакете - фабричный класс, который принимает все параметры и вызывает эти методы. Боб является неизменным за пределами этого пакета. Для обеспечения этого обязательно закройте свой jar-файл, чтобы конечные пользователи не могли создавать новые классы в одном пакете.

Примечание. Вы можете использовать мои аннотации JavaDude Bean, чтобы упростить создание: http://code.google.com/p/javadude/wiki/Annotations

Например:

@Bean(writer=Access.PROTECTED, // all setXXX methods will be protected
    properties={
        @Property(name="name"),
        @Property(name="age", type=int.class)
    })
public class Person extends PersonGen {
}

Создание геттеров и конструктора в затмении

В Eclipse есть несколько хороших инструментов для быстрого запуска:

  1. Создание класса бобов
  2. Добавьте поля, которые вы хотите
  3. Щелкните правой кнопкой мыши в окне редактора
  4. Выберите «Источник» -> «Создать геттеры и сеттеры»
  5. Нажмите кнопку «Выбрать добытчиков»
  6. Нажмите ок
  7. Щелкните правой кнопкой мыши в окне редактора
  8. Выберите Source-> Generate Constructors from fields
  9. Выберите и закажите нужные поля в конструкторе
  10. Нажмите ок

Неизменяемость Decorator

Другая идея состоит в том, чтобы определить ваш bean-компонент с помощью методов получения и установки (вы можете использовать вышеописанную технику, но включая методы установки), затем вы можете создать для него класс-оболочку, который имеет только методы получения.

0 голосов
/ 16 апреля 2009

Шаг 1 : создайте новый класс и присвойте ему переменные экземпляра с точно такими же именами, что и переменные экземпляра вашего «большого объекта Java-бина». Этот новый класс не должен иметь сеттеров (но только геттеров), чтобы сделать его неизменным.

Шаг 2 : Используйте Apache Commons BeanUtils.copyProperties , чтобы скопировать все свойства (т.е. переменные экземпляра) из вашего «большого объекта Java-бина» в ваш новый объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...