Мне интересно, не хватает ли мне чего-нибудь в Java Beans. Мне нравится, чтобы мои объекты выполняли как можно большую инициализацию в конструкторе и имели минимальное количество мутаторов. Бобы, кажется, прямо противоположны этому и обычно кажутся неуклюжими. Какие возможности я упускаю из-за того, что не строю свои объекты как Beans?




Бины настроены таким образом, чтобы автоматизированные инструменты могли создавать и изменять Бины. Они не обязательно должны быть отличными шаблонами дизайна.
Примеры этих инструментов:
Хорошим примером может служить Hibernate, которому нужны геттеры и сеттеры для доступа к сохраняемым свойствам.
Я думаю, что struts, spring и подобные веб-фреймворки используют Beans для автоматизации некоторых процессов создания веб-сайтов. Я бы не стал использовать бобы, если бы вам не пришлось.
Hibernate не требует геттеров и сеттеров. Может работать напрямую с полями. Он также может обходить ограничения доступа (т. Е. Использовать закрытые поля и методы), если это позволяет диспетчер безопасности. Однако при работе с финальным (в том числе частным) API некоторые оптимизации отключены.
I like my objects to do as much initialization in the constructor as possible and have a minimum number of mutators.
Выбор неизменных объектов - разумный выбор. Однако преимущество beans заключается в том, что фреймворки / инструменты / библиотеки могут определять во время выполнения свойства класса, не требуя от вас реализации определенного интерфейса.
Например, предположим, что у вас есть коллекция bean-компонентов Person, и каждый bean-компонент имеет такие свойства, как имя, возраст, рост и т. д.
Вы можете отсортировать эту коллекцию beans по имени (например), используя следующий код:
Collection<Person> myCollection = // initialise and populate the collection
Comparator nameCompare = new BeanComparator("name");
Collections.sort(myCollection, nameCompare);
Класс BeanComparator знает, как извлечь свойство «name» из каждого объекта, потому что соблюдается соглашение Java Beans, т.е. вы избавляетесь от «накладных расходов» на реализацию интерфейса, такого как:
interface Nameable {
public String getName();
public void setName(String name);
}
Другой пример из Spring MVC - это bean-компонент, который хранит параметры URL-адреса запроса. Это можно определить в веб-контроллере (известном как «Действие» в Struts) следующим образом:
public ModelAndView searchUsers(UserSearchCriteria criteria) {
// implementation omitted
}
Поскольку ожидается, что UserSearchCriteria будет JavaBean, если URL-адрес запроса содержит параметр, такой как maxItems=6, инфраструктура Spring «знает», что она должна вызвать метод с подписью
void setMaxItems(int maxItems);
По сути, JavaBeans - это просто простое соглашение, которое позволяет динамически обнаруживать свойства класса во время выполнения (обычно с помощью инструмента или фреймворка), когда неудобно / невозможно заранее знать свойства, которые могут быть предоставлены.
BeanComparator неприятен. Отражение предназначено для времени разработки и фреймворков, а не для сердцевины цикла сортировки.
Похоже, вы на правильном пути. Не вы упускаете из виду Java Beans, это другие программисты неправильно их используют.
Спецификация Java Beans была разработана для использования с визуальными инструментами. Идея заключалась в том, что разработчик приложения сможет настроить экземпляр объекта в интерактивном режиме, а затем сериализовать (или сгенерировать код для) настроенного bean-компонента, чтобы его можно было реконструировать во время выполнения; намерение состояло в том, чтобы он не изменялся во время выполнения.
К сожалению, многие разработчики не понимают, что аксессоры нарушают инкапсуляцию. Они используют структуры вместо объектов. Они не видят ничего плохого в том, что другие классы, даже другие пакеты, зависят от членов данных класса.
Конечно, вам, как правило, потребуется настраивать экземпляры ваших объектов. Просто это нужно делать с помощью какой-то функции конфигурации. Это может быть контейнер для внедрения зависимостей, визуальный инструмент в стиле «BeanBox» или просто чтение файлов JSON, XML или свойств, которые вы написали вручную. Ключ в том, что во время выполнения эти объекты фактически неизменяемы; клиенты просто вызывают свои операции, они не имеют доступа к своим свойствам.
Holub следует определению инкапсуляции, которое я называю «сокрытием данных». Я предпочитаю «защиту данных». Игра заключается в том, чтобы знать, когда и как изменяются ваши данные. Пока сами данные являются конфиденциальными, вы контролируете изменения. В этот момент имеет значение, хотите ли вы, чтобы он был неизменным или нет.
Минимизация связи между типами значительно упрощает читаемость кода и обслуживание. Такие авторитеты, как Голуб, и мой собственный анекдотический опыт научили меня, что внешние зависимости от свойств объекта являются симптомами ненужной сложности. Обычно есть более простая и чистая альтернатива.
Когда вы слышите слово «фасоль», ожидайте увидеть какой-то «контейнер». Идея JavaBean любого вида состоит в том, чтобы предоставить единое соглашение об интерфейсе для компонентов, которые можно добавлять и которыми можно управлять во время выполнения. Plain JavaBeans - это самый простой пример этого: он предоставляет все возможности интерфейса и является сериализуемым, что означает, что вы можете создавать экземпляры bean-компонента, изменять их, сохранять и перезагружать их.
Давным-давно я написал редактор Java, который содержал простую «базу данных», представляющую текстовые строки, и имел «подключаемую архитектуру», которая использовала bean-компоненты. Вы можете добавить поведение в редактор, перетащив bean-компонент из хранилища bean-компонентов и перетащив его в редактор; как только вы это сделали, поведение (скажем, Cntl-T для транспонирования символов в курсоре) было автоматически доступно в редакторе. У bean-компонентов был известный интерфейс - они знали, как запрашивать у контейнера его структуру данных, и метод doSomething () - и контейнер знал, что нужно динамически загружать файл класса, создавать экземпляр объекта и устанавливать его доступ к база данных.
Между прочим, на самом деле не обязательно, чтобы аксессоры нарушали инкапсуляцию; однако верно, что только потому, что у вас есть член, вы не необходимость, чтобы предоставить ему методы получения и установки. В спецификации JavaBean это немного неясно; Дело в том, чтобы предоставить геттеры и сеттеры для тех вещей, которые должны быть в «контракте» объектов.
После того, как в язык были добавлены интроспекция и рефлексия, и они были действительно поняты, потребность в этих соглашениях несколько уменьшилась; в ранней версии Java для поиска методов требовалось соглашение.
Я разделяю идею, что минимизировать изменчивость - это хорошо. Как уже указывалось, преимущество JavaBeans в том, что с ними легко работать с помощью фреймворков.
Чтобы получить лучшее из «обоих миров», я думаю, что хороший вариант - использовать Строитель шаблон, слегка изменив Builder в соответствии со стандартом JavaBeans. Итак, если вам нужна функциональность фреймворка, которая требует, чтобы ваш класс соответствовал стандарту JavaBeans, вы можете использовать Builder вместо фактического класса.
Конечно. Стоит ли использовать какие-либо автоматизированные инструменты (помимо сериализации)? Примеры? Спасибо!