Что это такое
Паттерн Flyweight (Приспособленец) экономит память, когда программа держит тысячи похожих объектов: тяжёлая общая часть хранится один раз и на неё все ссылаются, а каждый объект хранит только свою маленькую уникальную часть.
Лесу из 10 000 деревьев не нужны 10 000 текстур — ему нужны 2 вида деревьев и 10 000 крошечных записей (x, y, вид).
Пример: лес из общих видов
GetKind() выдаёт общие объекты видов, создавая каждый только при первом запросе. Каждое дерево хранит лишь позицию и указатель.
Много деревьев, мало видов
Четыре дерева, но «создаётся вид» печатается только дважды — дуб и сосна существуют по одному экземпляру, каким бы большим ни стал лес.
Вывод: программа на Go и захваченный вывод
package main
import "fmt"
// Тяжёлая общая часть — создаётся один раз для каждого вида.
type TreeKind struct {
name string
texture string
}
var kinds = map[string]*TreeKind{}
func GetKind(name string) *TreeKind {
if k, ok := kinds[name]; ok {
return k
}
fmt.Println("создаётся вид:", name)
k := &TreeKind{name: name, texture: name + ".png"}
kinds[name] = k
return k
}
// Лёгкая часть каждого дерева: позиция и указатель.
type Tree struct {
x, y int
kind *TreeKind
}
func main() {
forest := []Tree{
{x: 1, y: 2, kind: GetKind("дуб")},
{x: 3, y: 4, kind: GetKind("сосна")},
{x: 5, y: 6, kind: GetKind("дуб")},
{x: 7, y: 8, kind: GetKind("сосна")},
}
fmt.Println("посажено деревьев:", len(forest))
fmt.Println("сохранено видов: ", len(kinds))
}
Когда его использовать
Используйте его, когда профилирование показывает нехватку памяти из-за множества объектов, повторяющих тяжёлые данные, — плитки карт, глифы, частицы, кэшированные стили.
Пропустите его, если объектов меньше тысяч или общая часть невелика. Это паттерн оптимизации: без проблемы с памятью он даёт только сложность.
Плюсы и минусы
Плюсы: большая экономия памяти на больших объёмах; общие данные обновляются в одном месте.
Минусы: общие объекты нужно считать доступными только для чтения — одна неосторожная запись изменит «каждый дуб в лесу»; разделение на общую и уникальную части усложняет модель.