Ответ
Абстрактная фабрика — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств связанных или зависимых объектов, не привязываясь к их конкретным классам.
Зачем он нужен? Чтобы гарантировать совместимость создаваемых объектов (например, все виджеты в приложении должны быть в одном стиле — 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) — придется менять интерфейс фабрики и все её реализации. - Усложнение кода из-за большого количества классов.