Перейти к основному содержимому

Что это такое

Паттерн Flyweight экономит память, когда программа хранит тысячи похожих объектов: тяжёлая общая часть сохраняется один раз, и на неё все ссылаются, а каждый объект хранит только свою небольшую уникальную часть.

Лесу из 10 000 деревьев не нужно 10 000 текстур — ему нужны 2 вида деревьев и 10 000 крошечных записей (x, y, вид).


Пример: лес с общими видами

getKind() выдаёт общие объекты видов из Map, создавая каждый только при первом запросе. Каждое дерево хранит лишь позицию и ссылку.

Много деревьев, мало видов

Деревьев четыре, но создаём вид печатается только дважды — дуб и сосна существуют по одному разу, каким бы большим ни стал лес. Две последние строки: посажено деревьев: 4 и сохранено видов: 2.

Prompt
Напишите программу на TypeScript с паттерном Flyweight: тяжёлый класс TreeKind (name, texture), который хранится по одному экземпляру на каждый вид в Map за функцией getKind, печатающей сообщение при создании вида, и лёгкие объекты Tree, содержащие только позицию и ссылку на свой вид. Посадите четыре дерева двух видов и напечатайте, сколько деревьев существует и сколько видов было сохранено.
Вывод: программа на TypeScript и захваченный вывод

Когда его использовать

Используйте его, когда профилирование показывает проблемы с памятью из-за множества объектов, повторяющих тяжёлые данные — тайлы карты, глифы, частицы, кэшированные стили.

Не используйте его, если объектов меньше тысяч или общая часть мала. Это паттерн оптимизации: без проблемы с памятью он остаётся просто лишней сложностью.


Плюсы и минусы

Плюсы: большая экономия памяти на больших объёмах; общие данные обновляются в одном месте.

Минусы: с общими объектами нужно обращаться как с доступными только для чтения — одна неосторожная запись изменит «каждый дуб в лесу» (помогает пометить общие поля как readonly); разделение на общую и уникальную части усложняет модель.