Flyweight — разделение общего состояния для экономии памяти
Flyweight позволяет хранить общее состояние объектов в одном экземпляре и разделять его между множеством клиентов. Вместо создания миллионов одинаковых объектов система выделяет общее «внутреннее» состояние, а уникальные параметры передаются извне.
Паттерн применяется там, где необходимо обработать большое количество мелких структур данных: справочники, каталоги, графические элементы, текстовые символы, шаблоны UI, метаданные и кэши.
Flyweight значительно снижает потребление памяти и уменьшает нагрузку на систему при работе с массивными данными.
Flyweight — один из редких паттернов, который напрямую связан с оптимизацией использования памяти и производительности. Его суть заключается в том, чтобы разделить состояние объектов на внутреннее (общие данные) и внешнее (переменные данные). Внутреннее состояние хранится в одном экземпляре — и множество объектов используют его совместно. Это позволяет избегать миллиона копий одинаковых структур.
Где используется Flyweight
Flyweight актуален в следующих сценариях:
1. Справочники и каталоги
Например, в системе есть сотни тысяч товаров, но категории, бренды, характеристики и типовые описания одинаковы для множества из них.
Вместо хранения повторяющихся строк или объектов система хранит:
-
одно описание категории,
-
одно описание бренда,
-
один объект характеристики.
А товар лишь ссылается на них.
Это резко снижает объём RAM и ускоряет поиск.
2. Графические системы
В графике Flyweight применяется для:
-
отображения миллионов пикселей,
-
рендеринга символов (шрифты),
-
повторяющихся UI-компонентов,
-
карт и геоданных.
Большинство фреймворков UI (Java AWT, .NET WPF, Android) используют Flyweight внутри.
3. Тексты, документы, IDE
Когда редактор отображает документ на 1 миллион символов, он не хранит для каждого символа объект шрифта.
Вместо этого:
-
«А» в размере 12 и шрифте Roboto — один объект
-
все появляющиеся «А» — используют один и тот же объект Flyweight.
Это критично для IDE, HTML-редакторов, PDF-генераторов.
4. Шаблоны UI и компонентные библиотеки
React, Vue, Flutter — используют концепции, похожие на Flyweight, чтобы:
-
переиспользовать виртуальные узлы,
-
уменьшать нагрузку на рендер,
-
избегать десятков тысяч одинаковых нод.
5. Системы высоких нагрузок
В сервисах с сотнями миллионов сущностей Flyweight применяется для:
-
экономии оперативной памяти,
-
ускорения поиска и фильтрации,
-
уменьшения GC пауз,
-
ускорения сериализации.
Например, пользовательские статусы, типы событий, типы транзакций вынесены в один экземпляр.
Как работает Flyweight
Каждый объект раскладывается на два типа свойств:
Внутреннее состояние
Общие данные, повторяющиеся у множества экземпляров.
Сохраняются один раз.
Внешнее состояние
Уникальные параметры (координаты, значения, id, состояние).
Внешнее состояние подается в метод объекта при использовании, а не хранится внутри.
Так объект становится «легковесным».
Преимущества
-
большая экономия памяти;
-
снижение нагрузки на GC;
-
уменьшение времени создания объектов;
-
увеличение скорости рендера и обработки данных;
-
повышение эффективности хранения справочников.
Недостатки
-
усложняет код;
-
требует тщательного контроля состояния;
-
вносит риск ошибок при неправильном разделении внутреннего и внешнего состояния;
-
может быть избыточен, если количество объектов не критично велико.
Архитектор должен оценивать оправданность применения.
Flyweight в учебниках
В книгах:
паттерн упоминается в разделах структурных моделей и при обсуждении оптимизации ресурсов.Чаще всего его связывают с компонентной архитектурой, объектным проектированием и оптимизацией больших наборов данных.
Почему архитектор обязан знать Flyweight
Потому что при проектировании справочников, каталогов, рендеринговых компонентов, UI-интерфейсов и массивных структур архитектор должен уметь:
-
экономить память,
-
минимизировать дублирование,
-
снижать нагрузку,
-
делать систему быстрой и масштабируемой.
Во всех крупных системах Flyweight появляется хотя бы в одном модуле.