Приведи пример использования принципа открытости/закрытости (Open-Closed Principle) в Dart/Flutter.

«Приведи пример использования принципа открытости/закрытости (Open-Closed Principle) в Dart/Flutter.» — вопрос из категории SOLID и принципы, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Принцип открытости/закрытости (OCP) гласит, что сущности (классы, модули) должны быть открыты для расширения, но закрыты для модификации. В Flutter это часто реализуется через композицию и абстракции.

Практический пример: система уведомлений. Допустим, у нас есть сервис, отправляющий уведомления пользователю. Вместо того чтобы модифицировать его каждый раз при добавлении нового канала, мы проектируем его, следуя OCP.

// Абстракция (открыта для расширения новыми реализациями)
abstract class NotificationService {
  Future<void> send(String message);
}

// Конкретные реализации (расширяют функциональность)
class EmailNotificationService implements NotificationService {
  @override
  Future<void> send(String message) async {
    // Логика отправки email
    print('Sending email: $message');
  }
}

class PushNotificationService implements NotificationService {
  @override
  Future<void> send(String message) async {
    // Логика отправки push-уведомления через Firebase
    print('Sending push: $message');
  }
}

// Класс, использующий сервис (закрыт для модификации)
class UserNotifier {
  final List<NotificationService> services;

  UserNotifier({required this.services});

  Future<void> notifyUser(String event) async {
    final message = 'Event occurred: $event';
    for (final service in services) {
      await service.send(message);
    }
  }
}

// Использование
void main() async {
  final notifier = UserNotifier(services: [
    EmailNotificationService(),
    PushNotificationService(),
    // Легко добавить новый канал, не меняя UserNotifier:
    // SmsNotificationService(),
  ]);

  await notifier.notifyUser('Login from new device');
}

Теперь, чтобы добавить отправку SMS, мне нужно лишь создать новый класс SmsNotificationService, реализующий NotificationService. Класс UserNotifier менять не требуется — он закрыт для модификаций.