Шаблон абстрактной фабрики

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

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

Паттерн «Абстрактная фабрика» предоставляет интерфейс для создания серии связанных или взаимозависимых объектов без указания конкретных классов реализации. Используя паттерн «Абстрактная фабрика», клиент может быть отделён от процесса создания конкретных продуктов, что позволяет клиенту создавать семейство продуктов через интерфейс фабрики.

summary

назначение

Предоставить интерфейс для создания серии связанных или взаимозависимых объектов без указания их конкретных классов.

В основном решает

Проблема выбора интерфейса.

Применимые сценарии

Когда системе нужно создавать несколько связанных или зависимых объектов без указания конкретных классов.

Решение

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

Ключевой код

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

Пример приложения

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

Преимущества

  1. Обеспечить совместную работу объектов из одного семейства продуктов.
  2. Клиенту не нужно знать конкретный класс каждого объекта, что упрощает код.

Недостатки

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

Сценарий использования

  1. Когда QQ меняет свой скин, весь набор скинов меняется вместе.
  2. При создании кроссплатформенных приложений генерируются программы для разных операционных систем.

Примечания

Добавить новое семейство продуктов относительно легко, но добавить новую иерархию продуктов сложнее.

Структура

Паттерн «Абстрактная фабрика» включает следующие основные роли:

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

Паттерн «Абстрактная фабрика» обычно включает семейство связанных продуктов, и каждый класс конкретной фабрики отвечает за создание конкретных продуктов в этом семействе. Клиент создает объекты продуктов, используя интерфейс абстрактной фабрики, не используя напрямую классы реализации конкретных продуктов.

Реализация

Мы создадимShapeиColorинтерфейсы и классы сущностей, реализующие эти интерфейсы. Следующий шаг — создать класс абстрактной фабрикиAbstractFactory. Далее определите классы фабрик.ShapeFactoryиColorFactory, и оба этих класса фабрик расширяютAbstractFactory. Затем создайте класс создателя/генератора фабрикFactoryProducer。

AbstractFactoryPatternDemoИспользование классаFactoryProducerЧтобы получитьAbstractFactoryобъект. Он передаст вAbstractFactoryПередайте информацию о фигуреShape(CIRCLE / RECTANGLE / SQUARE), чтобы получить тип нужного ему объекта. В то же время он такжеAbstractFactoryПередайте информацию о цветеColor(RED / GREEN / BLUE), чтобы получить тип нужного ему объекта.

抽象工厂模式的 UML 图

Шаг 1

Создайте интерфейс для фигур.

Shape.java

public interface Shape { void draw(); }

Шаг 2

Создайте конкретные классы, реализующие интерфейс.

Rectangle.java

Rectangle.java

public class Rectangle implements Shape { @Override public void draw() { System.out.println("Внутри метода Rectangle::draw()."); } }

Square.java

public class Square implements Shape { @Override public void draw() { System.out.println("Внутри метода Square::draw()."); } }

Circle.java

public class Circle implements Shape { @Override public void draw() { System.out.println("Внутри метода Circle::draw()."); } }

Шаг 3

Создайте интерфейс для цветов.

Color.java

public interface Color { void fill(); }

Шаг 4

Создайте конкретные классы, реализующие интерфейс.

Red.java

public class Red implements Color { @Override public void fill() { System.out.println("Внутри метода Red::fill()."); } }

Green.java

public class Green implements Color { @Override public void fill() { System.out.println("Внутри метода Green::fill()."); } }

Blue.java

public class Blue implements Color { @Override public void fill() { System.out.println("Внутри метода Blue::fill()."); } }

Шаг 5

Создайте абстрактный класс для получения фабрик объектов Color и Shape.

AbstractFactory.java

public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape); }

Шаг 6

Создайте классы фабрик, которые расширяют AbstractFactory, генерируя объекты классов сущностей на основе предоставленной информации.

ShapeFactory.java

public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override public Color getColor(String color) { return null; } }

ColorFactory.java

public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ return null; } @Override public Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); } else if(color.equalsIgnoreCase("GREEN")){ return new Green(); } else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } }

Шаг 7

Создайте класс-создатель/генератор фабрик, чтобы получать фабрики, передавая информацию о форме или цвете.

FactoryProducer.java

public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } }

Шаг 8

Используйте FactoryProducer для получения AbstractFactory и получайте объекты классов сущностей, передавая информацию о типе.

AbstractFactoryPatternDemo.java

public class AbstractFactoryPatternDemo { public static void main(String[] args) { //Получить фабрику фигур AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //Получить объект с фигурой Circle Shape shape1 = shapeFactory.getShape("CIRCLE"); //Вызовите метод draw у Circle shape1.draw(); //Получите объект, форма которого — Rectangle Shape shape2 = shapeFactory.getShape("RECTANGLE"); //Вызвать метод draw у Rectangle shape2.draw(); //Получить объект с фигурой Square Shape shape3 = shapeFactory.getShape("SQUARE"); //Вызвать метод draw у Square shape3.draw(); //Получить фабрику цветов AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //Получить объект с цветом Red Color color1 = colorFactory.getColor("RED"); //Вызвать метод fill у Red color1.fill(); //Получить объект с цветом Green Color color2 = colorFactory.getColor("GREEN"); //Вызвать метод fill у Green color2.fill(); //Получить объекты с цветом Blue Color color3 = colorFactory.getColor("BLUE"); //Вызвать метод fill у Blue color3.fill(); } }

Шаг 9

Выполните программу, выведите результат:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
Другие расширения