Что это такое
Паттерн Приспособленец (Flyweight) экономит память, когда программа хранит тысячи похожих объектов: тяжёлая общая часть хранится один раз и используется по ссылке везде, а каждый объект хранит только свою небольшую уникальную часть.
Лесу из 10 000 деревьев не нужны 10 000 текстур — ему нужны 2 вида деревьев и 10 000 крошечных записей (x, y, вид).
Пример: лес с общими видами
get_kind() выдаёт общие объекты видов из обычного словаря-кэша и создаёт каждый из них только при первом запросе. Каждое дерево хранит лишь позицию и ссылку.
Много деревьев, мало видов
Деревьев четыре, но «создаётся вид» выводится только дважды — oak и pine существуют в единственном экземпляре, каким бы большим ни стал лес.
Вывод: полная программа на Python
from dataclasses import dataclass
# Тяжёлая общая часть — создаётся один раз для каждого вида.
@dataclass
class TreeKind:
name: str
texture: str
kinds: dict[str, TreeKind] = {}
def get_kind(name: str) -> TreeKind:
if name in kinds:
return kinds[name]
print("создаётся вид:", name)
kind = TreeKind(name=name, texture=name + ".png")
kinds[name] = kind
return kind
# Лёгкая часть каждого дерева: позиция и ссылка.
@dataclass
class Tree:
x: int
y: int
kind: TreeKind
forest = [
Tree(x=1, y=2, kind=get_kind("oak")),
Tree(x=3, y=4, kind=get_kind("pine")),
Tree(x=5, y=6, kind=get_kind("oak")),
Tree(x=7, y=8, kind=get_kind("pine")),
]
print("посажено деревьев:", len(forest))
print("сохранено видов:", len(kinds))
Когда его использовать
Используйте его, когда профилирование показывает проблемы с памятью из-за множества объектов, повторяющих тяжёлые данные, — тайлы карты, глифы, частицы, кэшированные стили.
Не используйте его, если объектов меньше нескольких тысяч или общая часть невелика. Это паттерн оптимизации: без проблемы с памятью он лишь добавляет сложность.
Плюсы и минусы
Плюсы: большая экономия памяти при больших объёмах; общие данные обновляются в одном месте.
Минусы: общие объекты нужно считать доступными только для чтения — одна неосторожная запись изменит «каждый дуб в лесу»; разделение на общую и уникальную части усложняет модель.