Что такое паттерн Абстрактная фабрика?

«Что такое паттерн Абстрактная фабрика?» — вопрос из категории Паттерны, который задают на 44% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Зачем он нужен? Чтобы гарантировать совместимость создаваемых объектов (например, все виджеты в приложении должны быть в одном стиле — Material или Cupertino) и упростить замену целого семейства продуктов.

Пример на Dart/Flutter: Допустим, мы создаем UI, который должен работать и на Android, и на iOS с нативным видом.

// Абстрактные продукты: элементы UI
abstract class Button {
  void render();
}
abstract class Switch {
  void toggle();
}

// Конкретные продукты для Material Design
class MaterialButton implements Button {
  @override
  void render() => print('Rendering a Material button');
}
class MaterialSwitch implements Switch {
  @override
  void toggle() => print('Toggling a Material switch');
}

// Конкретные продукты для Cupertino (iOS)
class CupertinoButton implements Button {
  @override
  void render() => print('Rendering a Cupertino button');
}
class CupertinoSwitch implements Switch {
  @override
  void toggle() => print('Toggling a Cupertino switch');
}

// Абстрактная фабрика
abstract class UIWidgetsFactory {
  Button createButton();
  Switch createSwitch();
}

// Конкретные фабрики
class MaterialFactory implements UIWidgetsFactory {
  @override
  Button createButton() => MaterialButton();
  @override
  Switch createSwitch() => MaterialSwitch();
}

class CupertinoFactory implements UIWidgetsFactory {
  @override
  Button createButton() => CupertinoButton();
  @override
  Switch createSwitch() => CupertinoSwitch();
}

// Клиентский код
class SettingsPage {
  SettingsPage(this.factory);
  final UIWidgetsFactory factory;

  void buildUI() {
    final button = factory.createButton();
    final switcher = factory.createSwitch();
    button.render();
    switcher.toggle();
  }
}

void main() {
  // В зависимости от платформы выбираем фабрику
  final factory = Platform.isAndroid ? MaterialFactory() : CupertinoFactory();
  final page = SettingsPage(factory);
  page.buildUI(); // Все элементы будут в одном стиле
}

Плюсы:

  • Гарантирует совместимость объектов из одного семейства.
  • Изолирует клиентский код от конкретных классов продуктов.
  • Упрощает поддержку кода и добавление новых семейств.

Минусы:

  • Сложность добавления нового типа продукта (например, Slider) — придется менять интерфейс фабрики и все её реализации.
  • Усложнение кода из-за большого количества классов.