Инициализировать коллекцию внутри объекта? - PullRequest
9 голосов
/ 08 декабря 2008

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

Ответы [ 10 ]

7 голосов
/ 08 декабря 2008

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

   public class Division
    {
        private int divId;
        public int DivisionId { get; set; }

        private Collection<Employee> emps;
        public Collection<Employee> Employees
        { get {return emps?? (emps = new Collection<Employee>(DivisionId));}} 
    }

РЕДАКТИРОВАТЬ: этот шаблон реализации, как правило, не является потокобезопасным ... emps может считываться двумя разными потоками как null до того, как первый поток завершит его изменение. В этом случае это, вероятно, не имеет значения, так как DivisionId является неизменным, и хотя оба потока будут получать разные коллекции, они будут действительными. Поэтому, когда второй поток завершает работу, emps будет допустимой коллекцией. Вероятно, потому, что первый поток может начать использовать emps до того, как второй поток сбросит его. Это не будет потокобезопасным. Другая немного более сложная реализация от Jon SKeet является поточно-ориентированной (см. Эта статья о SIngletons для его примера / обсуждения того, как это исправить.

3 голосов
/ 08 декабря 2008

Это зависит от вашего контракта между вашим API и пользователем.

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

То есть, addFoo (Foo toAdd) вместо setFooSet (Set set) и т. Д.

Но это зависит от вас.

2 голосов
/ 08 декабря 2008

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

У меня также были реализации копирования при записи, которые обеспечивают неизменяемое представление, поскольку любая мутация создаст новую базовую коллекцию.

2 голосов
/ 08 декабря 2008

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

2 голосов
/ 08 декабря 2008

Обычно я создаю коллекцию, затем предоставляю методы для добавления / удаления элементов из внутренней коллекции, а не заставляю потребителя класса беспокоиться о проверке на нулевое значение. Это также дает вам возможность лучше контролировать то, что происходит с коллекцией. В конечном счете, это зависит от того, для чего он предназначен, но, скорее всего, если у вашего класса есть коллекция, то не только у потребителя класса может быть коллекция этих объектов. Иначе зачем им использовать ваш класс?

1 голос
/ 08 декабря 2008

Я пробовал оба пути, и я обычно счастлив, когда обнаружил, что уже создал его. В качестве альтернативы вы можете скрыть реализацию от потребителя за набором методов, которые могут обработать проверку для вас.

1 голос
/ 08 декабря 2008

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

1 голос
/ 08 декабря 2008

IMO, вот где IEnumerable входит хорошо.

Лично мне нравится, когда мои свойства 'collection' инициализируются пустыми списками.

1 голос
/ 08 декабря 2008

Я создаю пустую коллекцию. Конечно, он имеет небольшую стоимость памяти, но недостаточно большой, чтобы беспокоиться об этом.

0 голосов
/ 08 декабря 2008

Как правило, я думаю, что объект должен создавать коллекцию и предоставлять методы для ее манипулирования; добавить / получить / удалить. Следуя этому правилу, вы не должны предоставлять методы для настройки коллекции напрямую. Если для удобства вам нужен такой метод, как setSomeCollection (Collection someCollection), реализация этого метода не должна устанавливать ссылку в объекте, а копировать значения из коллекции параметров метода в коллекцию внутри объекта;

public void setSomeCollection(Collection someCollection) {
   this.someCollection.clear();
   this.someCollection.addAll(someCollection);
}

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

То же самое верно, если предоставить геттер; Вы должны либо вернуть копию своего внутреннего собрания, либо версию только для чтения. Apache commons-collection и google-collection предоставляют методы для создания неизменяемых оберток вокруг коллекции, а также те, которые поставляются с Java в пакете java.util; java.util.Collections.unmodifiable *.

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