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

Приведи пример использования паттернов программирования

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

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

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

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

Примеры использования паттернов программирования в Flutter

Паттерны программирования — это проверенные решения для общих проблем. В Flutter используется множество паттернов. Рассмотрю самые важные и их практическое применение.

1. Builder Pattern

// Builder паттерн — создание сложных объектов пошагово

class UserBuilder {
  String _name = '';
  String _email = '';
  int _age = 0;
  String? _phone;
  bool _isActive = true;
  
  UserBuilder setName(String name) {
    _name = name;
    return this;  // Для цепочки вызовов
  }
  
  UserBuilder setEmail(String email) {
    _email = email;
    return this;
  }
  
  UserBuilder setAge(int age) {
    _age = age;
    return this;
  }
  
  UserBuilder setPhone(String phone) {
    _phone = phone;
    return this;
  }
  
  UserBuilder setActive(bool isActive) {
    _isActive = isActive;
    return this;
  }
  
  User build() {
    if (_name.isEmpty || _email.isEmpty) {
      throw Exception('Name and email required');
    }
    return User(
      name: _name,
      email: _email,
      age: _age,
      phone: _phone,
      isActive: _isActive,
    );
  }
}

class User {
  final String name;
  final String email;
  final int age;
  final String? phone;
  final bool isActive;
  
  User({
    required this.name,
    required this.email,
    required this.age,
    this.phone,
    required this.isActive,
  });
}

// Использование
void main() {
  final user = UserBuilder()
    .setName('John Doe')
    .setEmail('john@example.com')
    .setAge(30)
    .setPhone('+1234567890')
    .setActive(true)
    .build();
  
  print(user.name);  // John Doe
}

2. Observer Pattern

// Observer паттерн — подписка на изменения

abstract class Observer {
  void update(String event);
}

class EventBus {
  final List<Observer> _observers = [];
  
  void subscribe(Observer observer) {
    _observers.add(observer);
  }
  
  void unsubscribe(Observer observer) {
    _observers.remove(observer);
  }
  
  void notify(String event) {
    for (final observer in _observers) {
      observer.update(event);
    }
  }
}

class EmailNotifier extends Observer {
  @override
  void update(String event) {
    print('Email: $event');
  }
}

class LoggerObserver extends Observer {
  @override
  void update(String event) {
    print('Log: $event');
  }
}

// Использование
void main() {
  final bus = EventBus();
  
  final emailNotifier = EmailNotifier();
  final logger = LoggerObserver();
  
  bus.subscribe(emailNotifier);
  bus.subscribe(logger);
  
  bus.notify('User logged in');
  // Output:
  // Email: User logged in
  // Log: User logged in
}

3. Strategy Pattern

// Strategy паттерн — различные алгоритмы

abstract class SortStrategy {
  List<int> sort(List<int> numbers);
}

class BubbleSort implements SortStrategy {
  @override
  List<int> sort(List<int> numbers) {
    final arr = List<int>.from(numbers);
    for (int i = 0; i < arr.length; i++) {
      for (int j = 0; j < arr.length - i - 1; j++) {
        if (arr[j] > arr[j + 1]) {
          final temp = arr[j];
          arr[j] = arr[j + 1];
          arr[j + 1] = temp;
        }
      }
    }
    return arr;
  }
}

class QuickSort implements SortStrategy {
  @override
  List<int> sort(List<int> numbers) {
    if (numbers.isEmpty) return [];
    // Реализация quicksort
    return numbers;
  }
}

class Sorter {
  final SortStrategy strategy;
  
  Sorter(this.strategy);
  
  List<int> sortNumbers(List<int> numbers) {
    return strategy.sort(numbers);
  }
}

// Использование
void main() {
  final numbers = [5, 2, 8, 1, 9];
  
  // Используем BubbleSort
  final bubbleSorter = Sorter(BubbleSort());
  print(bubbleSorter.sortNumbers(numbers));
  
  // Меняем на QuickSort
  final quickSorter = Sorter(QuickSort());
  print(quickSorter.sortNumbers(numbers));
}

4. Decorator Pattern

// Decorator паттерн — добавление функционала

abstract class Coffee {
  double getCost();
  String getDescription();
}

class SimpleCoffee implements Coffee {
  @override
  double getCost() => 2.0;
  
  @override
  String getDescription() => 'Simple Coffee';
}

abstract class CoffeeDecorator implements Coffee {
  final Coffee coffee;
  
  CoffeeDecorator(this.coffee);
  
  @override
  double getCost() => coffee.getCost();
  
  @override
  String getDescription() => coffee.getDescription();
}

class MilkDecorator extends CoffeeDecorator {
  MilkDecorator(Coffee coffee) : super(coffee);
  
  @override
  double getCost() => super.getCost() + 0.5;
  
  @override
  String getDescription() => '${super.getDescription()}, Milk';
}

class SugarDecorator extends CoffeeDecorator {
  SugarDecorator(Coffee coffee) : super(coffee);
  
  @override
  double getCost() => super.getCost() + 0.2;
  
  @override
  String getDescription() => '${super.getDescription()}, Sugar';
}

// Использование
void main() {
  Coffee coffee = SimpleCoffee();
  print('${coffee.getDescription()}: \$${coffee.getCost()}');
  
  coffee = MilkDecorator(coffee);
  print('${coffee.getDescription()}: \$${coffee.getCost()}');
  
  coffee = SugarDecorator(coffee);
  print('${coffee.getDescription()}: \$${coffee.getCost()}');
  
  // Output:
  // Simple Coffee: $2.0
  // Simple Coffee, Milk: $2.5
  // Simple Coffee, Milk, Sugar: $2.7
}

5. Adapter Pattern

// Adapter паттерн — совместимость интерфейсов

// Старый интерфейс
class OldPaymentSystem {
  void pay(double amount, String currency) {
    print('Processing $currency $amount with old system');
  }
}

// Новый интерфейс
abstract class NewPaymentGateway {
  Future<bool> processPayment(PaymentRequest request);
}

class PaymentRequest {
  final double amount;
  final String currency;
  final String cardToken;
  
  PaymentRequest({
    required this.amount,
    required this.currency,
    required this.cardToken,
  });
}

// Adapter
class PaymentAdapter implements NewPaymentGateway {
  final OldPaymentSystem _oldSystem;
  
  PaymentAdapter(this._oldSystem);
  
  @override
  Future<bool> processPayment(PaymentRequest request) async {
    _oldSystem.pay(request.amount, request.currency);
    return true;
  }
}

// Использование
void main() async {
  final oldSystem = OldPaymentSystem();
  final adapter = PaymentAdapter(oldSystem);
  
  final request = PaymentRequest(
    amount: 100.0,
    currency: 'USD',
    cardToken: 'token_123',
  );
  
  final result = await adapter.processPayment(request);
  print('Payment successful: $result');
}

6. MVC Pattern в Flutter

// Model
class User {
  final int id;
  final String name;
  final String email;
  
  User({
    required this.id,
    required this.name,
    required this.email,
  });
}

// View
class UserListView extends StatelessWidget {
  final List<User> users;
  
  const UserListView({required this.users});
  
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: users.length,
      itemBuilder: (context, index) {
        final user = users[index];
        return ListTile(
          title: Text(user.name),
          subtitle: Text(user.email),
        );
      },
    );
  }
}

// Controller
class UserController extends ChangeNotifier {
  List<User> _users = [];
  
  List<User> get users => _users;
  
  Future<void> fetchUsers() async {
    _users = [
      User(id: 1, name: 'John', email: 'john@example.com'),
      User(id: 2, name: 'Jane', email: 'jane@example.com'),
    ];
    notifyListeners();
  }
}

// Использование
class UserPage extends StatefulWidget {
  @override
  State<UserPage> createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
  final _controller = UserController();
  
  @override
  void initState() {
    super.initState();
    _controller.addListener(() => setState(() {}));
    _controller.fetchUsers();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Users')),
      body: UserListView(users: _controller.users),
    );
  }
}

7. Repository Pattern

// Repository паттерн — абстракция доступа к данным

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

class LocalUserRepository implements UserRepository {
  final List<User> _cache = [];
  
  @override
  Future<User?> getUserById(int id) async {
    return _cache.firstWhereOrNull((u) => u.id == id);
  }
  
  @override
  Future<List<User>> getAllUsers() async => _cache;
  
  @override
  Future<void> createUser(User user) async {
    _cache.add(user);
  }
  
  @override
  Future<void> updateUser(User user) async {
    // Обновить
  }
  
  @override
  Future<void> deleteUser(int id) async {
    _cache.removeWhere((u) => u.id == id);
  }
}

class RemoteUserRepository implements UserRepository {
  final ApiClient _api;
  
  RemoteUserRepository(this._api);
  
  @override
  Future<User?> getUserById(int id) => _api.get('/users/$id');
  
  @override
  Future<List<User>> getAllUsers() => _api.get('/users');
  
  @override
  Future<void> createUser(User user) => _api.post('/users', user);
  
  @override
  Future<void> updateUser(User user) => _api.put('/users/${user.id}', user);
  
  @override
  Future<void> deleteUser(int id) => _api.delete('/users/$id');
}

// Использование
class UserService {
  final UserRepository _repository;
  
  UserService(this._repository);
  
  Future<List<User>> loadUsers() => _repository.getAllUsers();
  
  Future<void> saveUser(User user) => _repository.createUser(user);
}

8. BLoC Pattern (Popular in Flutter)

// BLoC = Business Logic Component

enum UserEvent { load, refresh }
enum UserState { initial, loading, loaded, error }

class UserBloc extends Bloc<UserEvent, UserState> {
  final UserRepository _repository;
  
  UserBloc(this._repository) : super(UserState.initial) {
    on<UserEvent>((event, emit) async {
      if (event == UserEvent.load || event == UserEvent.refresh) {
        emit(UserState.loading);
        try {
          final users = await _repository.getAllUsers();
          emit(UserState.loaded);
        } catch (e) {
          emit(UserState.error);
        }
      }
    });
  }
}

// Использование
class UserListPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => UserBloc(repository),
      child: BlocBuilder<UserBloc, UserState>(
        builder: (context, state) {
          if (state == UserState.loading) {
            return CircularProgressIndicator();
          }
          if (state == UserState.loaded) {
            return UserListView();
          }
          return Text('Error loading users');
        },
      ),
    );
  }
}

Резюме

Основные паттерны в Flutter:

  1. Builder — создание сложных объектов
  2. Observer — подписка на события
  3. Strategy — разные алгоритмы
  4. Decorator — добавление функционала
  5. Adapter — совместимость интерфейсов
  6. MVC — разделение concerns
  7. Repository — абстракция доступа к данным
  8. BLoC — управление бизнес-логикой

Правило: Используй паттерны когда они решают реальную проблему, не усложняй код без необходимости!

Приведи пример использования паттернов программирования | PrepBro