← Назад к вопросам
Приведи пример использования принципа interface segregation
2.0 Middle🔥 111 комментариев
#Архитектура Flutter#ООП и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример использования принципа Interface Segregation (ISP) в Dart/Flutter
Interface Segregation Principle (ISP) из SOLID гласит: клиент не должен зависеть от интерфейсов, которые он не использует. Вместо одного большого интерфейса создавай несколько маленьких, специфичных.
Концепция ISP
// Интерфейс Segregation = разделение на узкие интерфейсы
// вместо одного толстого интерфейса
// ❌ Плохо: Один большой интерфейс
abstract class Animal {
void eat();
void sleep();
void fly(); // Но не все животные летают!
void swim(); // Но не все животные плавают!
void bark(); // Но не все издают звуки!
}
class Dog implements Animal {
@override
void eat() => print('Dog eats');
@override
void sleep() => print('Dog sleeps');
@override
void fly() => throw UnimplementedError(); // Ненужный метод!
@override
void swim() => throw UnimplementedError(); # Может не нужен
@override
void bark() => print('Woof!');
}
// ✅ Хорошо: Маленькие, специфичные интерфейсы
abstract class Eater {
void eat();
}
abstract class Sleeper {
void sleep();
}
abstract class Flyer {
void fly();
}
abstract class Swimmer {
void swim();
}
abstract class VocalAnimal {
void makeSound();
}
class Dog implements Eater, Sleeper, VocalAnimal {
@override
void eat() => print('Dog eats');
@override
void sleep() => print('Dog sleeps');
@override
void makeSound() => print('Woof!');
// Никаких ненужных методов!
}
class Duck implements Eater, Sleeper, Flyer, Swimmer, VocalAnimal {
@override
void eat() => print('Duck eats');
@override
void sleep() => print('Duck sleeps');
@override
void fly() => print('Duck flies');
@override
void swim() => print('Duck swims');
@override
void makeSound() => print('Quack!');
}
Практический пример: User Management System
❌ Плохо: Один большой интерфейс
// Слишком много методов!
abstract class User {
String getName();
String getEmail();
void setEmail(String email);
void setPassword(String password);
bool canDelete();
bool canEdit();
bool canManageUsers();
bool canViewAnalytics();
bool canPublishContent();
void publishContent();
void viewAnalytics();
void manageUsers();
List<Role> getRoles();
List<Permission> getPermissions();
Future<void> sendNotification(String message);
Future<void> sendEmail(String subject, String body);
void logActivity(String action);
void updateLastLogin();
Map<String, dynamic> toJson();
String toXml();
String toCsv();
}
// Администратор должен реализовать всё
class AdminUser implements User {
// 20+ методов!
// Много ненужных методов
}
// Гость должен реализовать всё
class GuestUser implements User {
// 20+ методов, но большинство вернёт false или выбросит ошибку
// Очень неудобно
}
✅ Хорошо: Разделены на маленькие интерфейсы
// Основная информация о пользователе
abstract class UserProfile {
String getName();
String getEmail();
void setEmail(String email);
}
// Безопасность
abstract class UserAuthentication {
void setPassword(String password);
bool verifyPassword(String password);
}
// Права доступа
abstract class UserAuthorization {
bool canDelete();
bool canEdit();
List<Permission> getPermissions();
}
// Публикация контента
abstract class ContentPublisher {
void publishContent(String content);
void unpublishContent(String contentId);
}
// Просмотр аналитики
abstract class AnalyticsViewer {
Map<String, dynamic> getAnalytics();
void viewReport(String reportId);
}
// Управление пользователями
abstract class UserManager {
void createUser(User user);
void deleteUser(int userId);
void assignRole(int userId, Role role);
}
// Уведомления
abstract class Notifiable {
Future<void> sendNotification(String message);
Future<void> sendEmail(String subject, String body);
}
// Логирование
abstract class Auditable {
void logActivity(String action);
void updateLastLogin();
}
// Сериализация
abstract class Serializable {
Map<String, dynamic> toJson();
String toXml();
String toCsv();
}
// Теперь каждый пользователь реализует только нужные интерфейсы
class AdminUser implements
UserProfile,
UserAuthentication,
UserAuthorization,
ContentPublisher,
AnalyticsViewer,
UserManager,
Notifiable,
Auditable,
Serializable {
@override
String getName() => 'Admin';
@override
String getEmail() => 'admin@example.com';
@override
void setEmail(String email) {}
@override
void setPassword(String password) {}
@override
bool verifyPassword(String password) => true;
@override
bool canDelete() => true; // Может удалять
@override
bool canEdit() => true; # Может редактировать
@override
List<Permission> getPermissions() => [Permission.all()];
// Остальные методы...
}
class ContentCreator implements
UserProfile,
UserAuthentication,
UserAuthorization,
ContentPublisher,
Notifiable,
Auditable {
// Только то, что нужно для создателя контента
// Нет методов управления пользователями
// Нет методов просмотра аналитики
@override
void publishContent(String content) => print('Publishing...');
@override
bool canDelete() => false; // Не может удалять
@override
bool canEdit() => true; // Может редактировать
// Другие методы...
}
class GuestUser implements UserProfile, Notifiable {
// Только профиль и уведомления
// Никаких прав и управления
@override
String getName() => 'Guest';
@override
String getEmail() => 'guest@example.com';
@override
void setEmail(String email) {
throw Exception('Guest cannot change email');
}
@override
Future<void> sendNotification(String message) => print('Notification: $message');
}
Пример 2: Payment System
❌ Плохо: Толстый интерфейс платежа
abstract class PaymentGateway {
Future<PaymentResult> pay(double amount);
Future<RefundResult> refund(String transactionId);
Future<List<Transaction>> getTransactionHistory();
Future<void> validateCard(String cardNumber);
Future<void> setupRecurringPayment(double amount);
Future<void> cancelRecurringPayment();
bool supportsSplit();
Future<void> splitPayment(List<int> amounts);
Future<Map> getExchangeRate(String currency);
bool supportsInstallments();
Future<void> payWithInstallments(int months);
}
// Простой платёж может не поддерживать всё
class StripeGateway implements PaymentGateway {
// Много методов для реализации
// Некоторые не имеют смысла
}
✅ Хорошо: Маленькие, специфичные интерфейсы
// Базовый платёж
abstract class PaymentProcessor {
Future<PaymentResult> processPayment(PaymentData data);
}
// Возврат денег
abstract class Refundable {
Future<RefundResult> refund(String transactionId);
}
// История платежей
abstract class TransactionHistoryProvider {
Future<List<Transaction>> getTransactionHistory();
}
// Валидация карты
abstract class CardValidator {
Future<void> validateCard(String cardNumber);
}
// Подписки/Recurring платежи
abstract class RecurringPaymentSupport {
Future<void> setupRecurringPayment(double amount);
Future<void> cancelRecurringPayment();
}
// Разделение платежа
abstract class SplitPaymentSupport {
Future<void> splitPayment(List<int> amounts);
}
// Обмен валюты
abstract class CurrencyExchange {
Future<Map> getExchangeRate(String currency);
}
// Рассрочка
abstract class InstallmentSupport {
Future<void> payWithInstallments(int months);
}
// Stripe поддерживает основное
class StripeGateway implements
PaymentProcessor,
Refundable,
TransactionHistoryProvider,
CardValidator,
RecurringPaymentSupport {
@override
Future<PaymentResult> processPayment(PaymentData data) async {
// Реализация
return PaymentResult.success('stripe_tx_123');
}
@override
Future<RefundResult> refund(String transactionId) async {
// Реализация
return RefundResult.success();
}
// Остальные методы...
}
// Google Pay простой платёж
class GooglePayGateway implements PaymentProcessor, CardValidator {
@override
Future<PaymentResult> processPayment(PaymentData data) async {
return PaymentResult.success('google_pay_123');
}
@override
Future<void> validateCard(String cardNumber) async {}
// Только то, что нужно Google Pay
}
// PayPal поддерживает всё
class PayPalGateway implements
PaymentProcessor,
Refundable,
TransactionHistoryProvider,
RecurringPaymentSupport,
InstallmentSupport,
SplitPaymentSupport,
CurrencyExchange {
// Полная реализация
}
// Использование
class CheckoutService {
Future<void> processPayment(PaymentProcessor gateway) async {
// Работает с любым gateway который реализует PaymentProcessor
final result = await gateway.processPayment(paymentData);
print('Payment: $result');
}
Future<void> refundPayment(Refundable gateway, String txId) async {
// Работает только с Refundable gateway
final result = await gateway.refund(txId);
print('Refund: $result');
}
Future<void> setupSubscription(RecurringPaymentSupport gateway) async {
// Работает только с gateway поддерживающей recurring платежи
await gateway.setupRecurringPayment(99.99);
}
}
Пример 3: Database Repository
❌ Плохо: Большой интерфейс
abstract class Repository<T> {
Future<List<T>> findAll();
Future<T?> findById(int id);
Future<void> create(T entity);
Future<void> update(T entity);
Future<void> delete(int id);
Future<void> deleteAll();
Future<int> count();
Future<List<T>> findByQuery(String query);
Future<void> batchCreate(List<T> entities);
Future<void> batchDelete(List<int> ids);
Future<void> softDelete(int id);
Future<void> restore(int id);
Future<List<T>> findDeleted();
Stream<List<T>> watch();
}
✅ Хорошо: Разделены на маленькие
// Чтение
abstract class ReadOnlyRepository<T> {
Future<List<T>> findAll();
Future<T?> findById(int id);
}
// Создание
abstract class CreateRepository<T> {
Future<void> create(T entity);
Future<void> batchCreate(List<T> entities);
}
// Обновление
abstract class UpdateRepository<T> {
Future<void> update(T entity);
}
// Удаление
abstract class DeleteRepository<T> {
Future<void> delete(int id);
Future<void> deleteAll();
Future<void> batchDelete(List<int> ids);
}
// Мягкое удаление
abstract class SoftDeleteRepository<T> {
Future<void> softDelete(int id);
Future<void> restore(int id);
Future<List<T>> findDeleted();
}
// Поиск
abstract class SearchableRepository<T> {
Future<List<T>> findByQuery(String query);
}
// Статистика
abstract class CountableRepository<T> {
Future<int> count();
}
// Мониторинг
abstract class WatchableRepository<T> {
Stream<List<T>> watch();
}
// Полный репозиторий
class UserRepository implements
ReadOnlyRepository<User>,
CreateRepository<User>,
UpdateRepository<User>,
DeleteRepository<User>,
SoftDeleteRepository<User>,
SearchableRepository<User>,
CountableRepository<User>,
WatchableRepository<User> {
// Полная реализация
}
// Простой читаемый репозиторий
class ConfigRepository implements ReadOnlyRepository<Config> {
@override
Future<List<Config>> findAll() async => [];
@override
Future<Config?> findById(int id) async => null;
// Больше ничего не нужно
}
Преимущества ISP
// ✅ Клиент зависит только от нужных методов
class PaymentService {
Future<void> processPayment(PaymentProcessor gateway) async {
// Знаем только о processPayment
// Не нужно знать о refund, installments и т.д.
await gateway.processPayment(data);
}
}
// ✅ Легко добавлять новые функции
class RefundService {
Future<void> refundPayment(Refundable gateway, String txId) async {
// Работает только с Refundable
// Просто и понятно
await gateway.refund(txId);
}
}
// ✅ Легко тестировать
class MockPaymentGateway implements PaymentProcessor {
@override
Future<PaymentResult> processPayment(PaymentData data) async {
return PaymentResult.success('mock_tx');
}
// Остальные методы не нужны
}
Резюме ISP
Interface Segregation Principle:
-
Разделяй большие интерфейсы на маленькие
- Вместо 20 методов → несколько интерфейсов
-
Каждый интерфейс = одна ответственность
PaymentProcessorтолько для платежейRefundableтолько для возвратов
-
Клиент реализует только нужные интерфейсы
- SimplePayment не реализует Refundable
- GuestUser не реализует UserManager
-
Меньше зависимостей
- PaymentService зависит только от PaymentProcessor
- Не нужно знать о других методах
Результат:
- ✅ Чище код
- ✅ Проще тестировать
- ✅ Лучше архитектура
- ✅ Меньше связанности
- ✅ Легче добавлять функции