Статьи

Абстрактная фабрика или фабричный метод?

Сегодня я хотел бы рассказать вам о Factory Method Pattern и Абстрактной Factory Pattern . Цель статьи — помочь вам узнать, где следует использовать одно из них.

О чем мы будем говорить?

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

В Википедии вы можете найти следующие определения:

[…] Шаблон фабричных методов — это шаблон для создания, который использует фабричные методы для решения проблемы создания объектов без указания точного класса создаваемого объекта. [Шаблон фабричного метода, Википедия]

Суть шаблона абстрактной фабрики состоит в том, чтобы «обеспечить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов». [Абстрактный шаблон фабрики, Википедия]

Хорошо, когда мы знакомы с теорией, мы можем посмотреть, как она работает на практике.

Фабричный метод как именованный конструктор

Factory Method Pattern поможет вам сделать ваш код более читабельным.

Взгляните на класс Person:

1
2
3
4
5
6
7
8
9
public class Person {
   public Person(Person mum, Person dad) {
       // some code
   }
 
   public Person() {
       // some code
   }
}

Вам понятно, почему у нас есть два конструктора и почему оба они создают допустимый объект?

Было бы более очевидно, если бы код был похож на приведенный ниже?

01
02
03
04
05
06
07
08
09
10
11
public class Person {
   public static Person withParents(Person mum, Person dad) {
       // some code
   }
 
   public static Person anOrphan() {
       // some code
   }
   
   private Person() {}
}

Это лучше?

Я считаю, что вы видели классы с большим количеством конструкторов. Всегда ли было легко узнать, в чем были различия между созданными объектами? Не думаете ли вы, что использование Named Constructors — это решение, которое может сэкономить время человека, которому придется работать с кодом?

Сосредоточьтесь на интерфейсе

Хорошей практикой является концентрация внимания на обобщении, а не на спецификации. Фабричный метод Pattern может помочь вам в этом.

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

Благодаря этому будут опубликованы только интерфейс и класс, отвечающий за создание:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public interface Currency {}
 
class Zloty implements Currency {}
class Euro implements Currency {}
class Dolar implements Currency {}
 
public class Currencies {
   public static Currency dollar() {
       return new Dollar();
   }
   
   public static Currency euro() {
       return new Euro();
   }
   
   public static Currency zloty() {
       return new Zloty();
   }
}

В данном примере только интерфейс Валюта и класс Валют будут использоваться вне пакета. Это дает вам гораздо больше гибкости в случае каких-либо изменений. Единственное, о чем вам нужно беспокоиться — это API классов Currency и Currency. Все остальное, с точки зрения разработчика, который будет использовать этот код, не имеет значения.

Дать выбор

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public interface OSComponents {
   Window aWindow();
   Menu aMenu();
   Panel aPanel();
}
 
public interface Window {}
public interface Panel {}
public interface Menu {}
 
public class UnixComponents implements OSComponents {
   @Override
   public Window aWindow() {
       return new UnixWindow();
   }
 
   @Override
   public Menu aMenu() {
       return new UnixMenu();
   }
 
   @Override
   public Panel aPanel() {
       return new UnixPanel();
   }
}
 
public class WindowsComponents implements OSComponents {
   // code
}
 
public class iOSComponents implements OSComponents {
   // code
}

Теперь мы можем сосредоточиться только на интерфейсе, предоставляемом интерфейсом OSComponents. Мы не заботимся о какой-либо конкретной реализации.

Резюме

Вы должны использовать Abstract Factory Pattern, где создание конкретных объектов зависит от выбора. Вы создаете необходимый заводской объект и передаете его дальше. Код, который манипулирует им, заинтересован только в интерфейсах.

Фабричный метод Pattern следует использовать, когда вы хотите объяснить, какая логика стоит за созданием объекта в данном состоянии (именованный конструктор), или когда вы хотите опубликовать только интерфейс, а не всю группу классов, которые его реализуют.

Надеюсь, эта статья поможет вам принять решение, когда вы должны использовать конкретное решение.

Но может это еще не все? Если вы заметили что-то, что я пропустил, пожалуйста, поделитесь этим, разместив свой комментарий ниже.

Ссылка: Абстрактная фабрика или фабричный метод? от нашего партнера JCG Себастьяна Малаки в блоге « Давайте поговорим о Java» .