Звезда не активнаЗвезда не активнаЗвезда не активнаЗвезда не активнаЗвезда не активна
 

Использует разделение для эффективной поддержки большого числа мелких объектов.

Назначение

Использует разделение для эффективной поддержки множества мелких объектов.

Применимость

Эффективность паттерна приспособленец во многом зависит от того, как и где он используется. Применяйте этот паттерн, когда выполнены все нижеперечисленные условия:

  • в приложении используется большое число объектов;
  • из-за этого накладные расходы на хранение высоки;
  • большую часть состояния объектов можно вынести вовне;
  • многие группы объектов можно заменить относительно небольшим количеством разделяемых объектов, поскольку внешнее состояние вынесено;
  • приложение не зависит от идентичности объекта. Поскольку объекты-приспособленцы могут разделяться, то проверка на идентичность возвратит "истину" для концептуально различных объектов.

Структура

Участники

  • Flyweight - приспособленец - объявляет интерфейс, с помощью которого приспособленцы могут получать внешнее состояние или как-то воздействовать на него;
  • ConcreteFlyweight - конкретный приспособленец - реализует интерфейс Flyweight и добавляет при необходимости внутреннее состояние. Объект класса ConcreteFlyweight должен быть разделяемым. Любое сохраняемое им состояние должно быть внутренним, т.е. не зависящим от контекста;
  • UnsharedConcreteFlyweight - неразделяемый конкретный приспособленец - не все подклассы обязательно должны быть разделяемыми. Интерфейс Flyweight допускает разделение, но не навязывает его. Часто у объектов UnsharedConcreteFlyweight на некотором уровне структуры приспособленца есть потомки в виде объектов класса ConcreteFlyweight.
  • FlyweightFactory - фабрика приспособленцев:
    • создает объекты-приспособленцы и управляет ими;
    • обеспечивает должное разделение приспособленцев. Когда клиент запрашивает приспособленца, объект ConcreteFlyweight предоставляет существующий экземпляр или создает новый, если готового еще нет.
  • Client - клиент:
    • хранит ссылки на обного или нескольких приспособленцев;
    • вычисляет или хранит внешнее состояние приспособленцев;

Результаты

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

Экономия памяти возникает по ряду причин:

  • уменьшение общего числа экземпляров;
  • сокращение объема памяти, необходимого для хранения внутреннего состояния;
  • вычисление а не хранение внешнего состояния (если это действительно так).

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

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