Конструктор со всеми свойствами класса или конструктор по умолчанию с установщиками?

StackOverflow https://stackoverflow.com/questions/830657

  •  06-07-2019
  •  | 
  •  

Вопрос

Ниже приведены два подхода:

  • конструктор со всеми свойствами класса

Плюсы:Мне нужно указать точное количество типов параметров, поэтому, если я допущу ошибку, компилятор предупредит меня (кстати, есть ли способ предотвратить проблему ошибочного переключения двух целых чисел в список параметров?)

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

  • сеттеры и пустой конструктор по умолчанию

Плюсы:Я четко вижу, что устанавливаю, поэтому, если я делаю что-то не так, я могу точно определить это, как только набираю это (я не могу совершить предыдущую ошибку при переключении двух переменных одного и того же типа).

Минусы:создание экземпляра объекта с множеством свойств может занять несколько строк (не знаю, действительно ли это мошенничество), и если я забуду установить свойство, компилятор ничего не скажет.

Что вы будете делать и почему?Знаете ли вы какой-нибудь шаблон освещения (учтите, что его следует использовать каждый раз, когда создается объект с более чем 7 свойствами), который можно предложить?Я спрашиваю об этом, потому что мне не нравятся большие конструкторы, в которых я не могу быстро понять, где находится искомая переменная, с другой стороны, я считаю, что «установить все свойства» уязвимо из-за отсутствия некоторых свойств.

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

Обновление - я нашел вопрос, связанный с этим: Создание больших неизменяемых объектов без использования конструкторов с длинными списками параметров.

Это было полезно?

Решение

Вы можете взглянуть на шаблон Builder, предложенный Джошуа Блохом и описанный в Эффективная Java.Презентация с основными тезисами есть на http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2689.pdf;без сомнения, вы могли бы найти ссылку получше.

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

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

Message message = new Message.Builder()
    .sender( new User( ... ) )
    .recipient( new User( ... ) )
    .subject( "Hello, world!" )
    .text( messageText )
    .build();

Фрагмент Message.Builder может выглядеть примерно так:

public class Builder {

    private User sender = null;
    // Other properties

    public Builder sender( User sender ) {
        this.sender = sender;
        return this;
    }
    // Methods for other properties

    public Message build() {
        Message message = new Message();
        message.setSender( sender );
        // Set the other properties
        return message;
    }

}

Другие советы

Вы упустили самый большой плюс конструктора с множеством параметров:он позволяет создавать неизменяемые типы.

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

Недавние академические исследования (CMU и Microsoft) по удобству использования API показывают, что конструкторы по умолчанию с сеттерами будут лучшим вариантом с точки зрения удобства использования.Это из статьи Джеффа Стилоса и Стивена Кларка «Последствия использования параметров в конструкторах объектов» и было представлено на Международной конференции по разработке программного обеспечения:

Абстрактный:Удобство использования API становится все более важным для продуктивности программистов.На основе опыта исследований удобства использования конкретных API были изучены методы изучения удобства использования вариантов дизайна, общих для многих API.Сравнительное исследование было проведено с целью оценить, как профессиональные программисты используют API с обязательными параметрами в конструкторах объектов в отличие от конструкторов «по умолчанию» без параметров.Была выдвинута гипотеза, что обязательные параметры позволят создать более удобные и самодокументируемые API, помогая программистам правильно использовать объекты и предотвращая ошибки.Однако в ходе исследования было обнаружено, что, вопреки ожиданиям, программисты предпочитали и были более эффективны с API, не требующими параметров конструктора.Поведение участников было проанализировано с использованием структуры когнитивных измерений и выявило, что требуемые параметры конструктора мешают общим стратегиям обучения, вызывая нежелательное преждевременное участие.

Вы упоминаете об этом в своем посте, но я считаю, что это важный момент, заслуживающий большего внимания:если только каждый входной параметр не относится к разным типам, большая проблема с огромными конструкторами заключается в том, что они очень легко транспонировать пару переменных.Компилятор — ненадежная система безопасности: некоторые ошибки он обнаружит, но те, которые проскользнут, будет гораздо труднее обнаружить и отладить.Тем более, что список ввода для огромного конструктора довольно непрозрачен, если только API не открыт в другом окне.

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

До этой темы я никогда не слышал о шаблоне Builder, о котором упоминает Роб.Сам никогда им не пользовался (очевидно), но это чертовски интригует.

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

Например, если у вас есть что-то вроде этого:

class Contact
{
    public Contact(string firstName, string lastName, string phoneNumber,
        string street, string city, string state, int zipCode) { ... }
}

Я бы реорганизовал его так:

class Contact
{
    public Contact(Person person, PhoneNumber number, Address address) { ... }
}

class Person
{
    public Person(string firstName, string lastName) { ... }
}

class PhoneNumber
{
    public PhoneNumber(string digits) { ... }
}

class Address
{
    public Address(string street, string city, string state, int zipCode) { ... }
}

Слишком большие классы — действительно распространенная проблема проектирования в ООП-кодовых базах.

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

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

сеттеры и пустой конструктор по умолчанию

JRL косвенно затронула эту тему, но одна из причин рассмотреть возможность использования сеттеров состоит в том, чтобы объект соответствовал Спецификация JavaBean.Это делает экземпляры поддающимися редактирование с помощью инструментов самоанализа и настойчивости, используя определенные методы сериализации.

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

Мне тоже нравится шаблон Builder, но самое важное правило:Всегда используйте свой мозг и находите дизайн, который лучше всего соответствует конкретной проблеме.Не существует универсального решения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top