Лучшая практика для создания объектов в Java - PullRequest
2 голосов
/ 14 октября 2011

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

Более того, Блох говорит, что стиль построения Java Bean также имеет недостатки.Источник: http://www.javapractices.com/topic/TopicAction.do?Id=84

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

Как мне создать объект, если я пытаюсь избегать конструкторов и Java-бинов?

Я пропускаю точку?Какова лучшая практика?

РЕДАКТИРОВАТЬ:

class Foo{
   private Foo(){}

   public Foo Create(){
      return new Foo();
   }

}

Ответы [ 8 ]

7 голосов
/ 14 октября 2011

Используйте конструкторы, пока не начнете чувствовать недостатки, которые упоминает Блох.Затем подумайте, лучше ли фабрики, внедрение зависимостей или какой-то другой подход.

2 голосов
/ 14 октября 2011

Используйте конструкторы для простых объектов с небольшим количеством аргументов. Если количество аргументов возрастает, тогда начинайте думать о сборщике или фабрике, как предлагает bloch.

В большинстве простых случаев конструкторы делают работу аккуратно.

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

Если вы используете фабричный шаблон для всех ваших конструкций объектов, он выглядит не очень хорошо.

  • также НИКОГДА НЕ ИСПОЛЬЗУЙТЕ сеттеры, подобные Java-бобам, в ваших классах, если для этого нет веской причины. вызывается для изменения состояния объекта. Объекты должны быть построены с максимально возможным количеством деталей через конструктор, сделать их как можно более неизменными, если не сделать их всего несколькими способами обновить состояние объекта только одним или двумя методами.
1 голос
/ 14 октября 2011

Если бы вы наткнулись на программу, которая занималась математикой, чтобы выяснить, в какой день недели это было повсеместно, что бы вы подумали? Вы, вероятно, подумали бы, что «математика для определения того, какой это день недели, должна быть в собственном методе, поэтому его можно выразить один раз и только один раз, причем метод вызывается везде, где код должен знать, в какой день». недели это ".

Построение объекта ничем не отличается от выяснения, какой это день недели. Сделайте это в одном месте, создайте этот метод и вызывайте этот метод везде, где вам нужен новый объект.

Теперь, в некоторых случаях, этот метод сам может быть конструктором (конструктор на самом деле просто забавный метод, верно?). В других случаях метод вызывает конструктор, который больше нигде не будет использоваться. Это зависит от того, сколько работы нужно сделать для создания объекта, и насколько вы хотите скрыть класс создаваемого объекта (представьте фабричный метод createDaysOfTheWeek - он может вернуть Collection<DayOfTheWeek> и скрыть факт что это ArrayList или LinkedHashSet или EnumSet или что-то еще). Обертывание конструкции в фабричном методе дает вам больше инкапсуляции, но меньше прозрачности. Оба эти качества необходимы для создания хорошего кода, но, как и пиво и пироги, вы должны иметь баланс между ними.

1 голос
/ 14 октября 2011

Ну, я думаю, что парень ссылается на паттерн «Инверсия контроля»:

http://en.wikipedia.org/wiki/Inversion_of_control

Чтобы не делать здесь диссертацию, я просто скажу, что инверсия управления в этом узком контексте инстанцирования объектов связана с тем фактом (и преимуществами), что отдельная служба имеет дело с инстанцированием объектов, а не от того, что нужно их инстанцировать. объекты вручную. Один из способов добиться этого - это Factory Pattern, который, как вы говорите, описывает парень. Другой вариант - использовать среду, которая делает IOC для вас, например Spring:

http://static.springsource.org/spring/docs/2.0.x/reference/beans.html

(что на самом деле не так уж далеко от фабричного образца)

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

Идея здесь не в том, чтобы прекратить использование конструктора для создания экземпляров, вы всегда используете его для получения ваших экземпляров, идея здесь в том, КОГДА и КАК вы вызываете этот конструктор:

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

У обоих способов есть свои преимущества. Чаще всего лучше разбираться с экземплярами отдельно и не делать это вручную, поскольку это приводит к созданию более чистого, менее связанного и более тестируемого кода.

1 голос
/ 14 октября 2011

Возможно, вам будет интересно ознакомиться с шаблоном Dependency Injection , где Google Guice является одной из самых популярных платформ для его реализации.

1 голос
/ 14 октября 2011

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

0 голосов
/ 14 октября 2011

Вы можете создать объект, используя Cinstructor, например, используя new, как показано в следующем примере:

Foo f=new Foo();

Существует концепция с именем singleton. В этом случае вы можете использовать этот тип, как показано выше, но сделайте функцию create статичной, иначе пользователь будет вызывать функцию create следующим образом:

class Foo{
   private Foo(){}

   public static Foo Create(){
      return new Foo();
   }

}
0 голосов
/ 14 октября 2011

Всегда судите рекомендацию в контексте. Конструкторы являются стандартным способом создания объекта, но они не лишены недостатков.

Например, он говорит о каркасе поставщика услуг - это возможно только на фабричных методах построения объектов. Но дело в том, что вы не разрабатываете Service Provider Framework все время.

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

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

...