«1. Обзор

В этой статье мы обсудим шаблон проектирования «Абстрактная фабрика».

В книге Design Patterns: Elements of Reusable Object-Oriented Software утверждается, что абстрактная фабрика «предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов». Другими словами, эта модель позволяет нам создавать объекты, которые следуют общему шаблону.

Примером шаблона проектирования Abstract Factory в JDK является newInstance() класса javax.xml.parsers.DocumentBuilderFactory.

2. Пример шаблона проектирования абстрактной фабрики

В этом примере мы создадим две реализации шаблона проектирования метода фабрики: AnimalFactory и ColorFactory.

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

Сначала мы создадим семейство класса Animal, а позже будем использовать его в нашей абстрактной фабрике.

Вот интерфейс Animal:

public interface Animal {
    String getAnimal();
    String makeSound();
}

и конкретная реализация Duck:

public class Duck implements Animal {

    @Override
    public String getAnimal() {
        return "Duck";
    }

    @Override
    public String makeSound() {
        return "Squeks";
    }
}

Кроме того, именно таким образом мы можем создавать более конкретные реализации интерфейса Animal (например, Dog, Bear и т. д.). .

Абстрактная фабрика имеет дело с семействами зависимых объектов. Имея это в виду, мы собираемся представить еще одно семейство Color в виде интерфейса с несколькими реализациями (White, Brown,…).

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

Теперь, когда у нас есть несколько готовых семейств, мы можем создать для них интерфейс AbstractFactory:

public interface AbstractFactory<T> {
    T create(String animalType) ;
}

Далее мы реализуем AnimalFactory, используя шаблон проектирования Factory Method, который мы обсуждали в предыдущем разделе:

public class AnimalFactory implements AbstractFactory<Animal> {

    @Override
    public Animal create(String animalType) {
        if ("Dog".equalsIgnoreCase(animalType)) {
            return new Dog();
        } else if ("Duck".equalsIgnoreCase(animalType)) {
            return new Duck();
        }

        return null;
    }

}

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

Когда все это установлено, мы создадим класс FactoryProvider, который предоставит нам реализацию AnimalFactory или ColorFactory в зависимости от аргумента, который мы передаем методу getFactory():

public class FactoryProvider {
    public static AbstractFactory getFactory(String choice){
        
        if("Animal".equalsIgnoreCase(choice)){
            return new AnimalFactory();
        }
        else if("Color".equalsIgnoreCase(choice)){
            return new ColorFactory();
        }
        
        return null;
    }
}

3. Когда использовать шаблон абстрактной фабрики:

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

Хотя шаблон отлично подходит для создания предопределенных объектов, добавление новых может оказаться сложной задачей. Для поддержки нового типа объектов потребуется изменить класс AbstractFactory и все его подклассы.

4. Резюме

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

Наконец, как всегда, реализацию этих примеров можно найти на GitHub.