← Назад к вопросам

Приведи пример использования абстрактной фабрики

2.0 Middle🔥 171 комментариев
#ООП и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример использования абстрактной фабрики в Dart/Flutter

Абстрактная фабрика (Abstract Factory) — это паттерн проектирования, который позволяет создавать семейства связанных объектов без указания их конкретных классов. Очень полезен для кроссплатформенной разработки.

Концепция: Что такое Abstract Factory?

Абстрактная фабрика создаёт не один объект, а целое семейство объектов, которые работают вместе.

// Абстрактная фабрика определяет интерфейс
abstract class UIFactory {
  Button createButton();
  TextField createTextField();
  Checkbox createCheckbox();
}

// Конкретные фабрики для разных платформ
class AndroidUIFactory implements UIFactory {
  @override
  Button createButton() => AndroidButton();
  
  @override
  TextField createTextField() => AndroidTextField();
  
  @override
  Checkbox createCheckbox() => AndroidCheckbox();
}

class iOSUIFactory implements UIFactory {
  @override
  Button createButton() => iOSButton();
  
  @override
  TextField createTextField() => iOSTextField();
  
  @override
  Checkbox createCheckbox() => iOSCheckbox();
}

Практический пример: Тема приложения

// 1. Абстрактные компоненты (интерфейсы)
abstract class Button {
  void render();
  Color getBackgroundColor();
}

abstract class TextField {
  void render();
  Color getBorderColor();
}

abstract class Checkbox {
  void render();
  Color getCheckColor();
}

// 2. Light Theme (светлая тема)
class LightButton implements Button {
  @override
  void render() => print('Rendering light button');
  
  @override
  Color getBackgroundColor() => Colors.white;
}

class LightTextField implements TextField {
  @override
  void render() => print('Rendering light text field');
  
  @override
  Color getBorderColor() => Colors.grey[300]!;
}

class LightCheckbox implements Checkbox {
  @override
  void render() => print('Rendering light checkbox');
  
  @override
  Color getCheckColor() => Colors.blue;
}

// 3. Dark Theme (тёмная тема)
class DarkButton implements Button {
  @override
  void render() => print('Rendering dark button');
  
  @override
  Color getBackgroundColor() => Colors.grey[900]!;
}

class DarkTextField implements TextField {
  @override
  void render() => print('Rendering dark text field');
  
  @override
  Color getBorderColor() => Colors.grey[700]!;
}

class DarkCheckbox implements Checkbox {
  @override
  void render() => print('Rendering dark checkbox');
  
  @override
  Color getCheckColor() => Colors.amber;
}

// 4. Абстрактная фабрика
abstract class ThemeFactory {
  Button createButton();
  TextField createTextField();
  Checkbox createCheckbox();
}

// 5. Конкретные фабрики
class LightThemeFactory implements ThemeFactory {
  @override
  Button createButton() => LightButton();
  
  @override
  TextField createTextField() => LightTextField();
  
  @override
  Checkbox createCheckbox() => LightCheckbox();
}

class DarkThemeFactory implements ThemeFactory {
  @override
  Button createButton() => DarkButton();
  
  @override
  TextField createTextField() => DarkTextField();
  
  @override
  Checkbox createCheckbox() => DarkCheckbox();
}

// 6. Использование
class Application {
  final ThemeFactory _themeFactory;
  late Button _button;
  late TextField _textField;
  late Checkbox _checkbox;
  
  Application(this._themeFactory);
  
  void buildUI() {
    // Фабрика создаёт все компоненты для текущей темы
    _button = _themeFactory.createButton();
    _textField = _themeFactory.createTextField();
    _checkbox = _themeFactory.createCheckbox();
  }
  
  void render() {
    _button.render();
    _textField.render();
    _checkbox.render();
  }
}

void main() {
  // Выбираем тему
  final isLightMode = true;
  
  final themeFactory = isLightMode
    ? LightThemeFactory() as ThemeFactory
    : DarkThemeFactory();
  
  // Создаём приложение с выбранной темой
  final app = Application(themeFactory);
  app.buildUI();
  app.render();
  
  // Все компоненты будут светлой темы
}

Пример 2: Database провайдеры

// 1. Абстрактные операции БД
abstract class DatabaseConnection {
  Future<void> connect();
  Future<List<Map>> query(String sql);
  Future<void> insert(String table, Map<String, dynamic> data);
  Future<void> disconnect();
}

abstract class UserRepository {
  Future<User?> getUserById(int id);
  Future<List<User>> getAllUsers();
  Future<void> createUser(User user);
}

// 2. PostgreSQL реализация
class PostgresConnection implements DatabaseConnection {
  late PostgreSQLConnection _connection;
  
  @override
  Future<void> connect() async {
    print('Connecting to PostgreSQL');
    _connection = PostgreSQLConnection(
      'localhost',
      5432,
      'mydb',
    );
    await _connection.open();
  }
  
  @override
  Future<List<Map>> query(String sql) async {
    return await _connection.query(sql);
  }
  
  @override
  Future<void> insert(String table, Map<String, dynamic> data) async {
    // PostgreSQL вставка
  }
  
  @override
  Future<void> disconnect() async {
    await _connection.close();
  }
}

class PostgresUserRepository implements UserRepository {
  final DatabaseConnection _connection;
  
  PostgresUserRepository(this._connection);
  
  @override
  Future<User?> getUserById(int id) async {
    final result = await _connection.query(
      'SELECT * FROM users WHERE id = $id',
    );
    return result.isNotEmpty ? User.fromMap(result[0]) : null;
  }
  
  @override
  Future<List<User>> getAllUsers() async {
    final result = await _connection.query('SELECT * FROM users');
    return result.map((row) => User.fromMap(row)).toList();
  }
  
  @override
  Future<void> createUser(User user) async {
    await _connection.insert('users', user.toMap());
  }
}

// 3. SQLite реализация
class SqliteConnection implements DatabaseConnection {
  late Database _database;
  
  @override
  Future<void> connect() async {
    print('Connecting to SQLite');
    _database = await openDatabase('app.db');
  }
  
  @override
  Future<List<Map>> query(String sql) async {
    return await _database.rawQuery(sql);
  }
  
  @override
  Future<void> insert(String table, Map<String, dynamic> data) async {
    await _database.insert(table, data);
  }
  
  @override
  Future<void> disconnect() async {
    await _database.close();
  }
}

class SqliteUserRepository implements UserRepository {
  final DatabaseConnection _connection;
  
  SqliteUserRepository(this._connection);
  
  @override
  Future<User?> getUserById(int id) async {
    final result = await _connection.query(
      'SELECT * FROM users WHERE id = $id',
    );
    return result.isNotEmpty ? User.fromMap(result[0]) : null;
  }
  
  @override
  Future<List<User>> getAllUsers() async {
    final result = await _connection.query('SELECT * FROM users');
    return result.map((row) => User.fromMap(row)).toList();
  }
  
  @override
  Future<void> createUser(User user) async {
    await _connection.insert('users', user.toMap());
  }
}

// 4. Абстрактная фабрика
abstract class DatabaseFactory {
  DatabaseConnection createConnection();
  UserRepository createUserRepository();
}

// 5. Конкретные фабрики
class PostgresFactory implements DatabaseFactory {
  @override
  DatabaseConnection createConnection() => PostgresConnection();
  
  @override
  UserRepository createUserRepository() =>
    PostgresUserRepository(createConnection());
}

class SqliteFactory implements DatabaseFactory {
  @override
  DatabaseConnection createConnection() => SqliteConnection();
  
  @override
  UserRepository createUserRepository() =>
    SqliteUserRepository(createConnection());
}

// 6. Использование
void main() async {
  // Выбираем БД провайдер (например, из конфигурации)
  final dbProvider = 'postgres'; // или 'sqlite'
  
  final factory = dbProvider == 'postgres'
    ? PostgresFactory() as DatabaseFactory
    : SqliteFactory();
  
  final userRepository = factory.createUserRepository();
  
  // Код работает одинаково для обеих БД!
  final users = await userRepository.getAllUsers();
  print('Users: ${users.length}');
}

Пример 3: Платёжные системы

// 1. Абстрактные операции платежа
abstract class PaymentProcessor {
  Future<PaymentResult> processPayment(PaymentData data);
  Future<PaymentResult> refund(String transactionId);
}

abstract class PaymentUI {
  Widget buildPaymentForm();
  Widget buildConfirmationDialog();
}

// 2. Stripe реализация
class StripePaymentProcessor implements PaymentProcessor {
  @override
  Future<PaymentResult> processPayment(PaymentData data) async {
    print('Processing payment with Stripe');
    // Stripe API вызов
    return PaymentResult.success('stripe_tx_123');
  }
  
  @override
  Future<PaymentResult> refund(String transactionId) async {
    print('Refunding Stripe transaction: $transactionId');
    return PaymentResult.success('refund_123');
  }
}

class StripePaymentUI implements PaymentUI {
  @override
  Widget buildPaymentForm() => StripePaymentForm();
  
  @override
  Widget buildConfirmationDialog() => StripeConfirmationDialog();
}

// 3. PayPal реализация
class PayPalPaymentProcessor implements PaymentProcessor {
  @override
  Future<PaymentResult> processPayment(PaymentData data) async {
    print('Processing payment with PayPal');
    // PayPal API вызов
    return PaymentResult.success('paypal_tx_456');
  }
  
  @override
  Future<PaymentResult> refund(String transactionId) async {
    print('Refunding PayPal transaction: $transactionId');
    return PaymentResult.success('refund_456');
  }
}

class PayPalPaymentUI implements PaymentUI {
  @override
  Widget buildPaymentForm() => PayPalPaymentForm();
  
  @override
  Widget buildConfirmationDialog() => PayPalConfirmationDialog();
}

// 4. Абстрактная фабрика
abstract class PaymentFactory {
  PaymentProcessor createPaymentProcessor();
  PaymentUI createPaymentUI();
}

// 5. Конкретные фабрики
class StripeFactory implements PaymentFactory {
  @override
  PaymentProcessor createPaymentProcessor() => StripePaymentProcessor();
  
  @override
  PaymentUI createPaymentUI() => StripePaymentUI();
}

class PayPalFactory implements PaymentFactory {
  @override
  PaymentProcessor createPaymentProcessor() => PayPalPaymentProcessor();
  
  @override
  PaymentUI createPaymentUI() => PayPalPaymentUI();
}

// 6. Использование в приложении
class CheckoutPage extends StatefulWidget {
  @override
  State<CheckoutPage> createState() => _CheckoutPageState();
}

class _CheckoutPageState extends State<CheckoutPage> {
  late PaymentFactory _paymentFactory;
  late PaymentProcessor _processor;
  late PaymentUI _paymentUI;
  
  @override
  void initState() {
    super.initState();
    _initializePaymentMethod();
  }
  
  void _initializePaymentMethod() {
    // Выбираем способ платежа
    final paymentMethod = 'stripe'; // или 'paypal'
    
    _paymentFactory = paymentMethod == 'stripe'
      ? StripeFactory()
      : PayPalFactory();
    
    _processor = _paymentFactory.createPaymentProcessor();
    _paymentUI = _paymentFactory.createPaymentUI();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Checkout')),
      body: Column(
        children: [
          _paymentUI.buildPaymentForm(),
          ElevatedButton(
            onPressed: _processPayment,
            child: Text('Pay'),
          ),
        ],
      ),
    );
  }
  
  Future<void> _processPayment() async {
    final result = await _processor.processPayment(
      PaymentData(
        amount: 99.99,
        currency: 'USD',
      ),
    );
    
    if (result.isSuccess) {
      showDialog(
        context: context,
        builder: (context) => _paymentUI.buildConfirmationDialog(),
      );
    }
  }
}

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

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

// 1. Фиксирует семейства объектов
// Если добавляем новый компонент — добавляем его везде

// 2. Коллекции связанных объектов
// Light theme всегда совместим
final lightFactory = LightThemeFactory();
final button = lightFactory.createButton();  // LightButton
final field = lightFactory.createTextField();  // LightTextField
// Они совместимы между собой!

// 3. Независимость от конкретных классов
class MyApp {
  final ThemeFactory _factory;
  MyApp(this._factory);  // Не знаем, какая тема
}

// 4. Легко добавлять новые семейства
// Добавляем HighContrastTheme:
class HighContrastThemeFactory implements ThemeFactory {}
// Остальной код не меняется

Резюме

Abstract Factory:

  1. Создаёт семейства объектов — группы связанных объектов
  2. Инкапсулирует создание — скрывает конкретные классы
  3. Гарантирует совместимость — объекты работают вместе

Когда использовать:

  • Темы приложения (Light, Dark, HighContrast)
  • Разные БД провайдеры (PostgreSQL, SQLite, MongoDB)
  • Платёжные системы (Stripe, PayPal, ApplePay)
  • UI для разных платформ (Android, iOS, Web)
  • Разные конфигурации (development, staging, production)

Главное правило: Abstract Factory — когда есть семейства связанных объектов, которые должны быть совместимы!

Приведи пример использования абстрактной фабрики | PrepBro