Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПИАПС / knigaVAPO_v2.doc
Скачиваний:
363
Добавлен:
17.04.2018
Размер:
35.96 Mб
Скачать

Структура паттерна приспособленец (Flyweight)

Клиенты не создают приспособленцев напрямую, а запрашивают их у фабрики. Любые атрибуты (члены данных класса), которые не могут разделяться, являются внешним состоянием. Внешнее состояние передается приспособленцу при вызове его методов. При этом наибольшая экономия памяти достигается в том случае, если внешнее состояние не хранится, а вычисляется при вызове.

Участники

  • Flyweight (Glyph) - приспособленец: объявляет интерфейс, с помощью которого приспособленцы могут получать внешнее состояние или как-то воздействовать на него;

  • ConcreteFlyweight (Character) - конкретный приспособленец: реализует интерфейс класса Flyweight и добавляет при необходимости внутреннее состояние. Объект класса ConcreteFlyweight должен быть разделяемым. Любое сохраняемое им состояние должно быть внутренним, то есть не зависящим от контекста;

  • UnsharedConcreteFlyweight (Row, Column) - неразделяемый конкретный приспособленец: - не все подклассы Flyweight обязательно должны быть разделяемыми. Интерфейс Flyweight допускает разделение, но не навязывает его. Часто у объектов UnsharedConcreteFlyweight на некотором уровне структурыприспособленца есть потомки в виде объектов класса Concret eFlyweight, как, например, у объектов классов Row и Column;

  • FlyweightFactory - фабрика приспособленцев: создает объекты-приспособленцы и управляет ими; обеспечивает должное разделение приспособленцев. Когда клиент запрашивает приспособленца, объект FlyweightFactory предоставляет существующий экземпляр или создает новый, если готового еще нет;

  • Client - клиент: хранит ссылки на одного или нескольких приспособленцев; вычисляет или хранит внешнее состояние приспособленцев.

Отношения

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

  • клиенты не должны создавать экземпляры класса ConcreteFlyweight напрямую, а могут получать их только от объекта FlyweightFactory. Это позволит гарантировать корректное разделение.

Результаты

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

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

  • уменьшение общего числа экземпляров;

  • сокращение объема памяти, необходимого для хранения внутреннего состояния;

  • вычисление, а не хранение внешнего состояния (если это действительно так).

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

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

UML-диаграмма классов паттерна Flyweight

Классы, описывающие различных насекомых Ant (муравей), Locust (саранча) и Cockroach (таракан) могут быть "легковесными", потому что специфичная для экземпляров информация может быть вынесена наружу и затем, передаваться клиентом в запросе.

Пример паттерна Flyweight

Паттерн Flyweight использует разделение для эффективной поддержки большого числа мелких объектов. Телефонная сеть общего пользования ТФОП является примером Flyweight. Такие ресурсы как генераторы тональных сигналов (Занято, КПВ и т.д.), приемники цифр номера абонента, набираемого в тоновом наборе, являются общими для всех абонентов. Когда абонент поднимает трубку, чтобы позвонить, ему предоставляется доступ ко всем нужным разделяемым ресурсам.

Использование паттерна Flyweight

  • Убедитесь, что существует проблема повышенных накладных расходов.

  • Разделите состояние целевого класса на разделяемое (внутреннее) и неразделяемое (внешнее).

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

  • Создайте фабрику, которая может кэшировать и повторно использовать существующие экземпляры класса.

  • Для создания новых объектов клиент использует эту фабрику вместо оператора new.

  • Клиент (или третья сторона) должен находить или вычислять неразделяемое состояние и передавать его методам класса.

Особенности паттерна Flyweight

  • Если Flyweight показывает, как сделать множество небольших объектов, то Facade показывает, как представить целую подсистему одним объектом.

  • Flyweight часто используется совместно с Composite для реализации иерархической структуры в виде графа с разделяемыми листовыми вершинами.

  • Терминальные символы абстрактного синтаксического дерева Interpreter могут разделяться при помощи Flyweight.

  • Flyweight объясняет, когда и как могут разделяться объекты State.

Реализация паттерна Flyweight

Паттерн Flyweight показывает, как эффективно разделять множество мелких объектов. Ключевая концепция - различие между внутренним и внешним состояниями. Внутреннее состояние состоит из информации, которая не зависит от контекста и может разделяться (например, имя иконки, ее ширина и высота). Оно хранится в приспособленце (то есть в классе Icon). Внешнее состояние не может разделяться, оно зависит от контекста и изменяется вместе с ним (например, координаты верхнего левого угла для каждого экземпляра иконки). Внешнее состояние хранится или вычисляется клиентом и передается приспособленцу при вызове операций. Клиенты не должны создавать экземпляры приспособленцев напрямую, а получают их исключительно из объекта FlyweightFactory для правильного разделения.

#include <iostream.h>

#include <string.h>

 

class Icon

{

  public:

Соседние файлы в папке ПИАПС