Java-конструктор с большими аргументами или подход получения / установки Java-бина - PullRequest
26 голосов
/ 27 октября 2009

Я не могу решить, какой подход лучше для создания объектов с большим количеством полей (10+) (все обязательно), конструкторский подход геттера / сеттера. Конструктор, по крайней мере, вы обеспечиваете, чтобы все поля были установлены. Java Beans легче увидеть, какие переменные устанавливаются вместо огромного списка. Шаблон компоновщика здесь НЕ кажется подходящим, так как все поля являются обязательными, и компоновщик требует, чтобы вы поместили все обязательные параметры в конструктор компоновщика.

Спасибо, D

Ответы [ 18 ]

1 голос
/ 27 октября 2009

Действительно зависит от конкретного класса. Должно ли оно быть неизменным? Это простой объект значения без какого-либо поведения? Собираетесь ли вы сопоставить этот объект значения параметрам веб-службы или реляционной базе данных? Собираетесь ли вы его сериализовать? (Некоторым из этих вещей нужен конструктор по умолчанию). Не могли бы вы рассказать немного больше об объекте?

1 голос
/ 24 июля 2010

IMO, конструкторы не формируют хороший API при создании объектов, особенно когда количество аргументов велико и они одного типа.

new Person(String, String, String, String); // what the?? this is what may 
                                            // show up in IDEs

, где это на самом деле означает Персона (имя, фамилия, имя, пароль, (например, ради)

Как упоминает Клетус, шаблон Строителя с цепочкой хорош. Еще одно преимущество в компоновщике состоит в том, что , если объекты неизменяемы, компоновщик может возвращать тот же объект (в этом случае вы можете иметь закрытый конструктор пакета с 15 аргументами, которые только Строитель знает о). Строители также могут возвращать любой подтип объектов, которые они строят

Другой подход, который вы могли бы использовать, - рассмотреть возможность использования внутреннего DSL. Но это имеет смысл, только если вы создаете такие объекты, как конфигурации, запросы и т. Д. Посмотрите, имеет ли смысл иметь внутренний DSL в вашем случае.

У нас была похожая проблема в нашем проекте. Нам пришлось получить определенные значения из домашнего шлюза (наш продукт). Он поддерживал запрос-ответ, основанный на запросе XML-протокол через http. Но создание объекта Request для отправки в пользовательском интерфейсе было утомительным, с настройкой объектов Request с соответствующими параметрами и фильтрами и т. Д.

Изначально наш объект запроса выглядел так:

Request r = new Request("SET");
r.setAction("add"); // modify, add, delete
r.setModuleName("NPWIFI"):
r.addParameter(new Param("wifiAclMac", "aa:bb:cc:dd:ee:ff"));
r.addParameter(new Param("wifiCommit", "commit"));
r.setActionParam("wifiAclRowStatus")
r.addFilter(new Filter(Type.EQUALS, "wifiInterface", "wl0"));
r.addFilter(new Filter(Type.EQUALS, "wifiAclMac", "yourgateway"));

Resonse r = gwSession.sendRequest(r);

Итак, мы изменили его на внутренний DSL, который был похож на SQL, но только программный

Query q = DQL.add("wifiAclMac", "wifiCommit").into("NPWIFI").values
            ("aa:bb:cc:dd:ee:ff", "commit").withAp("wifiAclRowStatus")
            .where("wifiInterface").is("wl0")
            .and("wifiAclMac").is("aa:bb:cc:dd:ee:ff").end();

Объект DQL «построитель запросов» выполнил всю сборку с проверкой и также оказался очень удобным в использовании.

Строители и DSL - это элегантные и мощные средства создания и создания объектов, но посмотрите, что имеет смысл в вашем случае.

1 голос
/ 21 июля 2010

Это вопрос дизайна без сомнения. Вы должны взвесить удобочитаемость с легкостью. Конструктор из десяти аргументов проще, но может быть, а может и не быть более читабельным / поддерживаемым. Он также имеет меньше вызовов методов для включения и выключения стека вызовов. Задание десяти различных значений через сеттеры немного более читабельно и явно. Это не обязательно «проще» (хотя вы можете спорить обоими способами), и добавляет больше вызовов методов для включения и выключения стека вызовов.

Но вот еще несколько моментов, о которых стоит подумать. Даже с помощью конструктора с десятью аргументами вы можете попросить программиста передать значение null, пробел, false или ноль (в зависимости от объекта или примитива), что может быть, а может и не совпадать с вашим намерением. Единственный способ контролировать это - потенциально вызвать исключение в конструкторе. Это то, что вы действительно хотите сделать? Вы ожидаете такого поведения?

Конечно, устанавливая каждую переменную отдельно через сеттеры, вы не сможете узнать, когда вы закончите или не закончили создание объекта. Вот где шаблон Построителя, обсужденный выше, мог бы помочь. Сделайте так, чтобы он создал объект, установил значения, а затем подтвердил, что все установлены. Если чего-то не хватает, потому что программист решил не передавать что-то, то вы защищены. Ваш класс не должен делать больше, чем положено. (В конце концов, важно подумать о том, кто когда-нибудь будет использовать ваш класс. Они могут не понимать вашего намерения, несмотря на все великие Javadoc в мире.)

Наконец, я бы спросил, есть ли что-то, что вам нужно по умолчанию? Потому что, если некоторые вещи могут иметь значения по умолчанию, вы можете либо установить для них значения по умолчанию на уровне класса, либо установить для них значение по умолчанию в конструкторе (в зависимости от ваших идеалов программирования, которые, по вашему мнению, являются более конкретными и способствуют поведению вашего объекта) , Тогда вы могли бы потенциально «задавать» определенные поля, и вам нужно только переопределить их через установщики вручную или через установщики через Builder.

Опять же, вы сами должны решить эти вещи. Но, пожалуй, наиболее важным из всего этого является рассмотрение удобочитаемости, а не эффективности, чтобы сделать код более понятным, и создание API и поведения, которые программисты, которые придут после вас, не смогут использовать. Предвидеть защиту от злоупотреблений в вашем дизайне, что бы вы ни использовали.

1 голос
/ 27 октября 2009

Если все параметры являются обязательными, то я не вижу причин, почему бы не использовать конструктор. Однако, если это не так, тогда использование компоновщика кажется лучшим подходом.
Полагаться только на сеттеры - это, на мой взгляд, худшее решение, так как нечего требовать, чтобы все обязательные свойства были установлены. Конечно, если вы используете bean-компонент Spring Framework или другое подобное решение, то Java-бины прекрасно работают, так как после инициализации вы можете проверить, что все установлено.

1 голос
/ 27 октября 2009

Существуют ли варианты класса, которые могут принимать меньше аргументов, или только один, и он имеет десять свойств?

Является ли объект неизменным?

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

0 голосов
/ 24 июля 2010

Если все параметры действительно требуются, и вы не используете Spring для создания экземпляра bean-компонента, я бы определенно использовал конструктор с 10 параметрами. Совершенно очевидно, что все параметры действительно необходимы.

Если вы используете Spring (возможно, иногда) для создания bean-компонента или вам не очень нравится иметь много временных переменных в методе, который создает этот bean-компонент, вы также можете использовать методы getter и setter. Если вы также реализуете метод validate для проверки правильности объекта, у вас не должно возникнуть проблем.

Метод validate работает лучше всего, однако, если вы используете его последовательно; возможно, имея Validatable интерфейс. Он очень хорошо вписывается в рабочий процесс, если он является частью стиля программирования. Если есть только один или два класса, в которых используется эта парадигма, вероятно, это того не стоит. Вы когда-нибудь забудете вызвать validate () где-нибудь.

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

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

0 голосов
/ 27 октября 2009

Я бы избегал конструкторов с большим количеством аргументов. Классы с большим количеством аргументов в конструкторах могут быть громоздкими. Представьте, что у вас есть иерархия наследования с подклассами, каждый из которых имеет множество аргументов в своих конструкторах. Сколько работы будет, если будет необходимо изменить аргументы некоторых классов верхнего уровня.

Я бы передавал интерфейс вашему конструктору, который вы могли бы изменить, не нарушая код, или использовать подход Javabeans и не иметь конструктора arg.

0 голосов
/ 27 октября 2009

Могут ли ваши поля быть объединены в промежуточный объект? Например, если вы передаете 10 полей, которые описывают человека, то создайте объект PersonInfo для передачи этих данных. Я лично предпочитаю передавать все необходимые поля при создании объекта. Таким образом, вы не получите полуобожженный объект, который неизбежно будет использован и оскорблен.

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