Ответ
1. State Management как реализация Observer (Наблюдатель):
Пакет provider или riverpod — это классическая реализация паттерна Наблюдатель. Виджеты (наблюдатели) слушают изменения в объектах-состояниях (наблюдаемых).
// Пример с ChangeNotifier (наблюдаемый объект)
import 'package:flutter/material.dart';
class CounterModel with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Уведомляем всех слушателей (виджеты)
}
}
// Виджет-слушатель (Consumer)
class MyCounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
// Этот Text слушает изменения в CounterModel
Consumer<CounterModel>(
builder: (context, counter, child) => Text('Count: ${counter.count}'),
),
ElevatedButton(
onPressed: () => context.read<CounterModel>().increment(),
child: Text('Increment'),
),
],
);
}
}
2. Factory Method для создания платформо-зависимых виджетов:
abstract class DialogButton {
Widget build(BuildContext context);
}
class MaterialDialogButton implements DialogButton {
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: () {},
child: Text('OK'),
);
}
}
class CupertinoDialogButton implements DialogButton {
@override
Widget build(BuildContext context) {
return CupertinoButton(
onPressed: () {},
child: Text('OK'),
);
}
}
// Фабричный метод
DialogButton createDialogButton(TargetPlatform platform) {
switch (platform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
return CupertinoDialogButton();
default:
return MaterialDialogButton();
}
}
3. Singleton для глобального доступа к сервисам:
class AnalyticsService {
// Приватный конструктор
AnalyticsService._privateConstructor();
// Единственный экземпляр
static final AnalyticsService _instance = AnalyticsService._privateConstructor();
// Фабричный конструктор для доступа
factory AnalyticsService() => _instance;
void logEvent(String event) {
// Отправка события в Firebase Analytics и т.д.
print('Logged: $event');
}
}
// Использование в любом месте приложения
AnalyticsService().logEvent('screen_opened'); Ответ 18+ 🔞
А, ну вот, опять про паттерны заговорили! Слушай, я тут подумал — Flutter-то, он же на самом деле просто набор этих самых паттернов, обёрнутых в красивые виджеты. Как будто конструктор «Лего», только для взрослых дядек, которые код пишут. Давай разберём, что к чему, а то некоторые до сих пор думают, что provider — это просто магия какая-то, а не классический Observer, ёпта.
1. State Management — это же просто Наблюдатель, ядрёна вошь!
Вот смотри, берём provider или riverpod. Всё это — одна и та же песня, просто на новый лад. Есть объект-состояние (наш CounterModel), который орёт на всех углах: «Эй, я изменился!». А есть куча виджетов-подписчиков, которые его слушают и, как только услышат этот крик (notifyListeners()), сразу перерисовываются. Ничего нового, чистая классика, просто обёрнутая так, чтобы не выносила мозг.
// Это и есть наш "громкоговоритель" (Subject в Observer)
class CounterModel with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Кричит: "Бля, я обновился! Все ко мне!"
}
}
// А это слушатели (Observers), которые ушами хлопают
class MyCounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
// Consumer — это ухо, приложенное к громкоговорителю
Consumer<CounterModel>(
builder: (context, counter, child) => Text('Count: ${counter.count}'),
),
// Кнопка, которая заставляет громкоговоритель кричать
ElevatedButton(
onPressed: () => context.read<CounterModel>().increment(),
child: Text('Increment'),
),
],
);
}
}
Вот и вся магия. Никакой ебушки-воробушки, просто паттерн, которому сто лет в обед.
2. Factory Method — чтобы не париться с платформами.
А это вообще любимый трюк, когда нужно, чтобы на айфоне кнопка была одна, а на андроиде — другая. Вместо того чтобы везде городить if (platform == ios), делаем фабрику. Она, как хитрая жопа, смотрит — на чём мы, и выдаёт нужную реализацию. Удобно, чё.
// Общий интерфейс для кнопки. Все должны уметь строить себя.
abstract class DialogButton {
Widget build(BuildContext context);
}
// Конкретная кнопка под Material (Андроид)
class MaterialDialogButton implements DialogButton {
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: () {},
child: Text('OK'),
);
}
}
// Конкретная кнопка под Cupertino (iOS)
class CupertinoDialogButton implements DialogButton {
@override
Widget build(BuildContext context) {
return CupertinoButton(
onPressed: () {},
child: Text('OK'),
);
}
}
// Сама фабрика — мозги, которые решают, что кому выдать
DialogButton createDialogButton(TargetPlatform platform) {
switch (platform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
return CupertinoDialogButton(); // На iOS — стиль яблока
default:
return MaterialDialogButton(); // На всём остальном — Material
}
}
И не нужно в каждом виджете голову ломать. Создал кнопку через фабрику — и похуй, где оно запустится.
3. Singleton — когда нужен один-единственный царь и бог. Ну а это, бля, классика жанра. Нужен тебе один сервис аналитики на всё приложение, чтобы не плодить сущностей. Делаем синглтон. Все знают, где он живёт, и все к нему ходят. Главное — не злоупотреблять, а то получится глобальная помойка, в которую все складывают свои дела, а потом разбираться — волнение ебать, где что лежит.
class AnalyticsService {
// Прячем конструктор, чтобы никто не мог сделать новый экземпляр
AnalyticsService._privateConstructor();
// Вот он, наш единственный и неповторимый экземпляр
static final AnalyticsService _instance = AnalyticsService._privateConstructor();
// А это — дверь, через которую все к нему попадают
factory AnalyticsService() => _instance;
void logEvent(String event) {
// Пишем логи куда надо
print('Logged: $event');
}
}
// Используем где угодно. Всегда получаем один и тот же объект.
AnalyticsService().logEvent('screen_opened');
Вот и всё. Никакой сложной науки, просто старые добрые паттерны в новом флатерном кафтане. Главное — понимать, что под капотом, а не просто копипастить код, как мартышлюшка.