Фабричный образец в Яве - PullRequest
5 голосов
/ 22 июня 2009

Я работал с Java-кодом, который предположительно использует шаблон Factory, но я не полностью убежден в этом шаблоне.

Мой код делает это:

// the factory
class SomeFactoryImpl {
   Set<SomeClass> getSomeListOfObjects();
}

И где-то в коде:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

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

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

Мне кажется, что лучше, если метод create является статическим методом класса фабрики. Но я также уверен, что мое мнение не совсем «правильное».

Так может ли сообщество SO привести примеры, когда создание экземпляра объекта Factory лучше, чем использование статических методов создания?

Кроме того, я столкнулся с ответом на аналогичный вопрос, в котором перечислены эти ссылки и ответ: поэтому мне нужно четко знать разницу между FactoryMethodPattern , FactoryMethod и CreationMethod с примерами кода.

Ответы [ 5 ]

5 голосов
/ 22 июня 2009

Использование экземпляра фабрики показывает реальные преимущества в сочетании с внедрением зависимости.

Так в вашем примере вместо:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

Вы бы имели:

public ThisClass(SomeFactory someFactory) {
    this.factory = someFactory;
}   

потом позже ...

{ ...
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

Некоторые баллы:

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

Я знаю, что это только часть вашего вопроса ...

1 голос
/ 22 июня 2009

Прежде всего, вы забыли основную цель фабричного шаблона, я открыл книгу банды четырех, и там говорится:

"Определите интерфейс для создания объекта, но пусть подклассы решают, какой класс создать, например. Фабричный метод позволяет классу отложить создание экземпляров для подклассов."

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

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

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

1 голос
/ 22 июня 2009

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

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

0 голосов
/ 22 июня 2009

IMO, код, который у вас есть , является , действительно является правильным образцом шаблона GoF Abstract Factory , даже если его использование не совсем оптимально. Если я правильно помню, в книге GoF описывается взаимосвязь между фабриками (SomeFactory, SomeFactoryImpl) и продуктами (SomeClass), но при этом не раскрывается специфика создания экземпляров фабрик.

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

  1. Пусть другой класс (так сказать, «менеджер фабрики») выбирает реализацию фабрики на основе параметра (например, DriverManager в JDBC) или другой контекстной информации.
  2. Использовать какую-то инфраструктуру внедрения зависимостей.

Если идти с № 1, я лично обычно пытаюсь смоделировать его после JDBC, где:

  • Driver будет абстрактной фабрикой
  • Connections, Statements и т. Д. Являются продуктами
  • DriverManager (явно не указано в книге GoF) - это служебный класс, который выбирает фабрику для вас на основе URL JDBC, переданного в

(В этом случае DriverManager идет вперед и также создает продукт для вас, если вы используете методы getConnection(...), как это делают большинство.)

Чтобы привязать его к вашему вопросу, можно использовать JDBC, позвонив по номеру

new OracleDriver().connect(...)

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

Эта проблема меня тоже беспокоила, пока однажды я не понял, что этот паттерн на самом деле явно не говорит о том, как создаются фабрики.

Надеюсь, это ответит на ваш вопрос.

0 голосов
/ 22 июня 2009

Вот почему я создаю экземпляры фабричных объектов

  1. это позволяет мне создать фабрику, настроить ее (создать синие виджеты против красных виджетов и т. Д.), А затем сделать ее доступной для создания моих синих виджетов, красных виджетов по запросу. Обратите внимание, что это отличается от наличия RedWidgetFactory, BlueWidgetFactory. Конфигурация ортогональна типу (-ам) создаваемых объектов
  2. Это уменьшает возможные проблемы с многопоточностью, которые могут возникнуть при использовании одной фабрики (доступ через статический метод) в вашей системе. Возможно, это немного защищает, но я обнаружил, что это хорошее мышление (особенно в больших системах). Конечно, это зависит от того, как создаются ваши объекты (например, создает ли ваша фабрика базовые компоненты, которые являются общими)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...