← Назад к вопросам
Приведи пример использования абстрактной фабрики
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:
- Создаёт семейства объектов — группы связанных объектов
- Инкапсулирует создание — скрывает конкретные классы
- Гарантирует совместимость — объекты работают вместе
Когда использовать:
- Темы приложения (Light, Dark, HighContrast)
- Разные БД провайдеры (PostgreSQL, SQLite, MongoDB)
- Платёжные системы (Stripe, PayPal, ApplePay)
- UI для разных платформ (Android, iOS, Web)
- Разные конфигурации (development, staging, production)
Главное правило: Abstract Factory — когда есть семейства связанных объектов, которые должны быть совместимы!