Шаблоны проектирования важны для разработчиков, так как они предлагают решения для распространённых проблем, встречающихся в разработке ПО. Для Flutter-разработчиков понимание и использование этих шаблонов может значительно повысить эффективность, масштабируемость и поддержку их приложений. В этой статье рассматриваются пять ключевых шаблонов проектирования, которые должен знать каждый Flutter-разработчик: Singleton, Provider, Builder, Observer и MVC (Model-View-Controller).
1. Паттерн Singleton
Паттерн Singleton гарантирует, что у класса будет только один экземпляр и обеспечивает глобальную точку доступа к нему. Это особенно полезно в Flutter для управления общими ресурсами, такими как настройки конфигурации, базы данных или сетевые соединения.
Во Flutter паттерн Singleton можно реализовать с помощью приватного конструктора и статического экземпляра. Вот пример:
class MySingleton {
static final MySingleton _instance = MySingleton._internal();
// Приватный конструктор
MySingleton._internal();
// Публичный фабричный метод для возврата одного и того же экземпляра
factory MySingleton() {
return _instance;
}
void someMethod() {
print("Вызван метод экземпляра Singleton");
}
}
При вызове MySingleton()
вы всегда получаете один и тот же экземпляр, что гарантирует единообразный доступ к общим ресурсам.
Случаи использования
- Подключение к базе данных: Обеспечивает единственный экземпляр подключения, чтобы избежать множественных подключений.
- Настройки конфигурации: Поддерживает настройки для всего приложения.
2. Паттерн Provider
Паттерн Provider, являющийся основным в сообществе Flutter, упрощает управление состоянием, предоставляя простой способ доступа к данным и бизнес-логике из дерева виджетов. Он придерживается принципов инверсии управления (IoC) и внедрения зависимостей (DI).
Пакет Provider
предлагает простой способ реализации этого паттерна. Вот базовый пример:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Пример использования Provider')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Вы нажали кнопку столько раз:',
),
Consumer<Counter>(
builder: (context, counter, child) => Text(
'${counter.count}',
style: Theme.of(context).textTheme.headline4,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<Counter>().increment(),
tooltip: 'Увеличить',
child: Icon(Icons.add),
),
),
);
}
}
Случаи использования
- Управление состоянием: Управление и передача состояния в разных частях приложения.
- Внедрение зависимостей: Легкое внедрение зависимостей в дерево виджетов.
3. Паттерн Builder
Паттерн Builder помогает пошагово создавать сложные объекты. Он отделяет конструирование объекта от его представления, что позволяет использовать один и тот же процесс создания для различных представлений.
Во Flutter виджет Builder
является классическим примером и часто используется для создания виджетов, которые зависят от BuildContext
, недоступного на момент создания виджета.
import 'package:flutter/material.dart';
class MyCustomWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Builder(
builder: (BuildContext context) {
return Text(
'Привет, Flutter!',
style: Theme.of(context).textTheme.headline4,
);
},
);
}
}
Случаи использования
- Сложные элементы пользовательского интерфейса: Создание сложных виджетов, зависящих от контекста.
- Условный рендеринг: Отображение виджетов в зависимости от условий выполнения.
4. Паттерн Observer
Паттерн Observer определяет зависимость «один ко многим» между объектами, так что при изменении состояния одного объекта все его зависимые объекты уведомляются и автоматически обновляются. Этот паттерн важен для реализации систем обработки событий.
В Flutter этот паттерн широко используется в решениях для управления состоянием, таких как ChangeNotifier
и ValueNotifier
.
import 'package:flutter/material.dart';
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
void main() {
final counter = Counter();
counter.addListener(() {
print('Счетчик изменился: ${counter.count}');
});
counter.increment();
}
Случаи использования
- Обработка событий: Уведомление и обновление слушателей при изменении состояния.
- Реактивное программирование: Реализация реактивных потоков данных.
5. Паттерн MVC (Model-View-Controller)
Паттерн MVC разделяет приложение на три взаимосвязанных компонента: Model (логика данных), View (логика интерфейса) и Controller (бизнес-логика). Такое разделение помогает управлять сложностью приложения путем декомпозиции кода на управляемые части.
Хотя Flutter не навязывает определенный архитектурный шаблон, MVC можно реализовать вручную. Вот простой пример:
Model: Определяет структуру данных и бизнес-логику.
class CounterModel {
int _count = 0;
int get count => _count;
void increment() {
_count++;
}
}
View: Представляет пользовательский интерфейс.
import 'package:flutter/material.dart';
class CounterView extends StatelessWidget {
final int count;
final VoidCallback onIncrement;
CounterView({required this.count, required this.onIncrement});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Пример MVC')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Вы нажали кнопку столько раз:'),
Text(
'$count',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: onIncrement,
tooltip: 'Увеличить',
child: Icon(Icons.add),
),
);
}
}
Controller: Связывает Model и View, обрабатывает ввод пользователя и обновляет Model.
import 'package:flutter/material.dart';
class CounterController {
final CounterModel _model;
CounterController(this._model);
int get count => _model.count;
void increment() {
_model.increment();
}
}
void main() {
final model = CounterModel();
final controller = CounterController(model);
runApp(MyApp(controller: controller));
}
class MyApp extends StatelessWidget {
final CounterController controller;
MyApp({required this.controller});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterView(
count: controller.count,
onIncrement: controller.increment,
),
);
}
}
Случаи использования
- Сложные приложения: Разделение задач для управления сложностью.
- Масштабируемость: Легкое добавление новых функций без изменения других частей.
Заключение
Шаблоны проектирования — это важные инструменты в арсенале Flutter-разработчика. Освоив паттерны Singleton, Provider, Builder, Observer и MVC, вы сможете создавать надёжные, масштабируемые и поддерживаемые приложения. Эти паттерны не только решают распространённые проблемы, но и способствуют применению лучших практик и принципов проектирования в разработке ПО. Независимо от того, управляете ли вы состоянием, создаете ли сложные объекты, обрабатываете ли события или организуете архитектуру приложения, эти паттерны помогут вам найти эффективные и действенные решения.
Источник: https://medium.com/@ayhamxv12instagram/5-essential-design-patterns-every-flutter-engineer-should-master-09206ec077ee
Гик, хакинтошник, линуксоид, считаю себя flutter разработчиком. Завёл канал, в котором изначально хотел показывать как я с нуля и до бесконечности погрузился в дорвей тематику, а в итоге просто рассказываю о себе, своих успехах и неудачах в сайтах, приложениях, офлайн проектах. Добро пожаловать в