Фабричные конструкторы
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy. Урок 14 из 110.
factory constructor — это специальный конструктор, который не всегда создаёт новый экземпляр. В отличие от обычных конструкторов, factory constructor может вернуть существующий экземпляр, подтип или даже null (если допускается значение null). Вы объявляете его с помощью ключевого слова factory.
class Logger {
static final Logger _instance = Logger._internal();
// Приватный именованный конструктор
Logger._internal();
// Фабричный конструктор
factory Logger() {
return _instance;
}
}
Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // trueВ этом примере factory constructor всегда возвращает один и тот же instance. Независимо от того, сколько раз вы выполняете Logger(), вы получаете идентичный объект. Этот шаблон часто используется для реализации синглтонов.
Фабричные конструкторы отличаются от обычных конструкторов в одном ключевом отношении: у них нет доступа к this, поскольку они могут вообще не создавать новый экземпляр. Вместо этого они должны явно возвращать объект:
class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle();
if (type == 'square') return Square();
return Rectangle();
}
}
class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }Фабричные конструкторы полезны, когда вам нужен контроль над созданием instance, например для возврата кэшированных объектов, реализации пулов объектов или определения того, какой подтип создать на основе входных параметров.
Задание
ЛегкоДавайте создадим систему уведомлений, которая использует factory constructors для создания разных типов уведомлений на основе простой строковой входной величины.
Вы создадите два файла, чтобы организовать код:
notification.dart: Определите классNotification, который служит базовым для всех типов уведомлений. Ваш class должен содержать:- поле
String message - private named constructor
Notification._internal, который инициализирует message - factory constructor
Notification(String type, String message), который возвращает разные подтипы уведомлений в зависимости от параметраtype:- Если type имеет значение
'email', вернитеEmailNotification - Если type имеет значение
'sms', вернитеSMSNotification - В противном случае верните
PushNotification
- Если type имеет значение
- method
send(), который выводитSending: [message]
- поле
В том же файле создайте три подкласса, которые расширяют Notification:
EmailNotification: Переопределитеsend(), чтобы выводитьEmail: [message]SMSNotification: Переопределитеsend(), чтобы выводитьSMS: [message]PushNotification: Переопределитеsend(), чтобы выводитьPush: [message]
Каждому подклассу нужен constructor, который принимает message и передаёт его родительскому class с помощью super._internal(message).
main.dart: Импортируйте свой class уведомлений и создайте три уведомления с помощью factory constructor:- уведомление по электронной почте с message
'Welcome!' - SMS-уведомление с message
'Your code is 1234' - push-уведомление с message
'New update available'
send()для каждого уведомления в указанном выше порядке.- уведомление по электронной почте с message
Ожидаемый вывод:
Email: Welcome!
SMS: Your code is 1234
Push: New update availableПопробуйте сами
import 'notification.dart';
void main() {
// TODO: Создать email-уведомление с сообщением 'Welcome!'
// TODO: Create an SMS notification with message 'Your code is 1234'
// TODO: Create a push notification with message 'New update available'
// TODO: Вызвать send() для каждого уведомления по порядку
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн РепозиторийПотренируйтесь самостоятельно: Онлайн-компилятор Dart