Javenue logo

Javenue

Программирование на Java

Информационные технологии

Паттерн Abstract Factory в java - Абстрактная Фабрика

В предыдущей статье по проектированию был описан паттерн Factory Method. Как и было обещано, на этот раз мы рассмотрим шаблон проектирования под названием Abstract Factory.

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

Перед тем, как привести пример использования Фабрики на Java, рассмотрим небольшую диаграмму классов (с Paint я творю чудеса :)):

Диаграмма классов - Абстрактная Фабрика

Из диаграммы видно, что клент после ипользования Фабрики для создания объектов, манипулирует объектами на более высоком уровне абстракции.

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

public abstract class SquadronFactory {
  public abstract Mage createMage() {}

  public abstract Archer createArcher() {}
 
  public abstract Warrior createWarrior() {}
}

Интерфейсы персонажей будут следующие:

public interface Mage {
  public void cast();
}

public interface Archer {
  public void shoot();
}

public interface Warrior {
  public void attack();
}

Перейдем к конкретным классам:

public class ElfSquadronFactory extends SquadronFactory {
  public Mage createMage() {
    return new ElfMage();
  }

  public Archer createArcher() {
    return new ElfArcher();
  }
 
  public Warrior createWarrior() {
    return new ElfWarrior();
  }
}

public class ElfMage implements Mage {
  public void cast() {
    // использовать магию эльфов
  }
}

public class ElfArcher implements Archer {
  public void shoot() {
    // использовать лук эльфов 
  }
}

public class ElfWarrior implements Warrior {
  public void attack() {
    // использовать меч эльфов
  }
}

Аналогичные классы можно создать для других рас.

Ну а теперь перейдем к использованию выше описанных классов для создания отряда. Функция создания отрядов будет иметь следующий вид:

public void createSquadron (SquadronFactory factory) {
  Mage mage = factory.createMage();
  Archer archer = factory.createArcher();
  Warrior warrior = factory.createWarrior();
  ...
}

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

Хочу обратить ваше внимание на то, что абстрактная фабрика может быть не только абстрактным классом, но и интерфейсом, и конкретным классом. Конкретные фабрики чаще всего реализуют паттерн Singleton.

Используйте паттерн Абстрактная Фабрика в таких случаях:

  • система не должна зависеть от способа создания объектов;
  • система работает с одним из нескольких семейств объектов;
  • объекты внутри семейства взаимосвязаны.

Комментарии по поводу статьи приветствуются.



Комментариев: 5

  Выйти

  * для публикации комментариев нужно  

TheMega:

Я лично использую factory для следующей ситуации.

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

С какой бд они будут работать в определенный момент времени - неизвестно. И зависит это от многих факторов. Но в конечном счете всё, что необходимо - это актуальный на данный момент connection string. Так вот, вся логика, связанная с созданием этих коллекций, включая генерацию connection string’а и прочие предварительные заморочки, выносятся в отдельный класс.

Есть и другие подобные примеры. Многие программисты используют подобные решения для разных задач. И чтобы каждый раз не объяснять друг другу то, что я тут рассказываю, они придумали этому решению название “Factory”.

Nuru:

Хм, а почему использовать здесь abstract class вместо interface? Разве это не антипатерн? Насколько я помню abstract class тем и отличается от interface что при реализации его наследуются методы объявлены в нем явно а не abstract. А так получается, что он используется как интерфес =\

Baracuda:

Полносстью согласен с NURU, на счёт использование абстрактного класа… Думаю, что интерфейс был более к стати именно для даного примера. Но если бы наша SquadronFactory производила б не всех персонажей, а только несколько в определённой ситуации, то как раз абстрактный клас был бы более к стати, по скольку не пришлось бы реализововать все методы этого класа ,в отличии от интерфейса, где нужно что бы были реализованы все методы! Естественно это не касаеться слушаетелей в Java ,для некоторых интерфейсов там определены адаптеры….

Sergey:

Господа, Nuru и Baracuda, шаблон Abstract Factory, пришел к нам из базовой книги “банды четырех”. В ней, в качестве языка примеров, используется С++. В С++ - нет интерфейсов, но есть абстрактные классы и множественное наследование.

Автору статьи - спасибо! Всегда приятно читать технические статьи, написанные понятным языком. Не зря говорят: “кто внятно мыслит, тот внятно излагает”.

c0nst:

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