Есть ли недостаток в написании длинного конструктора? - PullRequest
9 голосов
/ 03 июня 2010

Влияет ли это на время загрузки приложения? или какие-либо другие проблемы при этом?

Ответы [ 7 ]

24 голосов
/ 03 июня 2010

Вопрос о том, что означает «длинный», неясен. Вот несколько возможных интерпретаций:

Интерпретация # 1: у конструктора много параметров

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

Вот цитата из Effective Java 2nd Edition, Item 2: Рассмотрим шаблон компоновщика, когда сталкиваемся со многими параметрами конструктора :

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

Шаблон телескопического конструктора выглядит примерно так:

public class Telescope {
    final String name;
    final int levels;
    final boolean isAdjustable;

    public Telescope(String name) {
        this(name, 5);
    }
    public Telescope(String name, int levels) {
        this(name, levels, false);
    }
    public Telescope(String name, int levels, boolean isAdjustable) {       
        this.name = name;
        this.levels = levels;
        this.isAdjustable = isAdjustable;
    }
}

И теперь вы можете делать любое из следующего:

new Telescope("X/1999");
new Telescope("X/1999", 13);
new Telescope("X/1999", 13, true);

В настоящее время вы не можете, однако, установить только name и isAdjustable и оставить levels по умолчанию. Вы можете обеспечить больше перегрузок конструктора, но очевидно, что число будет взорваться при увеличении количества параметров, и у вас может даже быть несколько аргументов boolean и int, которые действительно могут создать беспорядок.

Как вы можете видеть, это не очень приятный для написания шаблон, и даже менее приятный в использовании (что здесь означает "правда"? Что такое 13?).

Bloch рекомендует использовать шаблон построителя, который позволит вам написать что-то вроде этого:

Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();

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

Смотри также

Похожие вопросы


Интерпретация # 2: конструктор выполняет большую работу, которая стоит времени

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

Вот некоторая цитата из Effective Java 2nd Edition, Item 17: Разработка и документация для наследования, или же запретить его :

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

Вот пример для иллюстрации:

public class ConstructorCallsOverride {
    public static void main(String[] args) {
        abstract class Base {
            Base() { overrideMe(); }
            abstract void overrideMe(); 
        }
        class Child extends Base {
            final int x;
            Child(int x) { this.x = x; }
            @Override void overrideMe() {
                System.out.println(x);
            }
        }
        new Child(42); // prints "0"
    }
}

Здесь, когда конструктор Base вызывает overrideMe, Child не завершил инициализацию final int x, и метод получает неправильное значение. Это почти наверняка приведет к ошибкам и ошибкам.


Интерпретация # 3: конструктор выполняет большую часть работы, которую можно отложить

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

Однако рассмотрим Effective Java 2nd Edition, Item 71: Используйте ленивую инициализацию разумно . Ленивая инициализация может привести к незначительным ошибкам, и не всегда дает улучшенную производительность, которая оправдывает добавленную сложность. Не преждевременно оптимизировать.

1 голос
/ 03 июня 2010

Самым большим недостатком, вероятно, является то же, что и написание любой другой длинной функции - она ​​может быть сложной и трудной для понимания.

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

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

1 голос
/ 03 июня 2010

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

0 голосов
/ 03 июня 2010

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

0 голосов
/ 03 июня 2010

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

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

0 голосов
/ 03 июня 2010

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

0 голосов
/ 03 июня 2010

Конструктор - это еще одна функция. Вам нужны очень длинные функции, вызываемые много раз, чтобы заставить программу работать медленно. Поэтому, если он вызывается только один раз, обычно не имеет значения, сколько кода внутри.

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