Читайте также:
|
// подготовить массивы с характеристиками компонентов
/
// определить, где должны быть точки разрыва
int breakCount;
breakCount = _compositor->Compose(
natural, stretchability, shrinkability, componentCount, _lineWidth, breaks
// разместить компоненты с учетом точек разрыва
Теперь рассмотрим подклассы класса Compositor. Класс SimpleCompositor для определения позиций точек разрыва исследует компоненты по одному:
class SimpleCompositor: public Compositor { public:
SimpleCompositor();
virtual int Compose(
Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[]
Класс TeXCompositor использует более глобальную стратегию. Он рассматривает абзац целиком, принимая во внимание размеры и растягиваемость компонентов. Данный класс также пытается равномерно «раскрасить» абзац, минимизируя ширину пропусков между компонентами:
class TeXCompositor: public Compositor { public:
TeXCompositor();
virtual int Compose(
Coord natural[], Coord stretch[]. Coord shrink[], int componentCount, int lineWidth, int breaks[]
);
//... };
Класс ArrayCompositor разбивает компоненты на строки, оставляя между ними равные промежутки:
class ArrayCompositor: public Compositor { public:
ArrayCompositor(int interval);
Паттерны поведения
virtual int Compose(
Coord natural!], Coord stretch!], Coord shrink!], int componentCount, int lineWidth, int breaks[]
j
He все из этих классов используют в полном объеме информацию, переданную операции Compose. SimpleComposiLor игнорирует растягиваемость компонентов, принимая во внимание только их естественную ширину. TeXCompositor использует всю переданную информацию, a ArrayCompositor игнорирует ее.
При создании экземпляра класса Composition вы передаете ему компоновщик, которым собираетесь пользоваться:
Composition* quick = new Composition (new SimpleCompositor); Composition* slick = new Composition (new TeXCompositor); Composition* iconic = new Composition (new ArrayCompositor (100));
Интерфейс класса Compositor тщательно спроектирован для поддержки всех алгоритмов размещения, которые могут быть реализованы в подклассах. Вряд ли вам захочется изменять данный интерфейс при появлении каждого нового подкласса, поскольку это означало бы переписывание уже существующих подклассов. В общем случае именно интерфейсы классов Strategy и Context определяют, насколько хорошо паттерн стратегия соответствует своему назначению.
Известные применения
Библиотеки ЕТ++ [WGM88] и Interviews используют стратегии для инкапсуляции алгоритмов разбиения на строки - так, как мы только что видели.
В системе RTL для оптимизации кода компиляторов [JML92] с помощью стратегий определяются различные схемы распределения регистров (RegisterAllocator) и политики управления потоком команд (RISCscheduler, CISCscheduler). Это позволяет гибко настраивать оптимизатор для разных целевых машинных архитектур.
Каркас ЕТ++ SwapsManager предназначен для построения программ, рассчитывающих цены для различных финансовых инструментов [EG92]. Ключевыми абстракциями для него являются Instrument (инструмент) и YieldCurve (кривая дохода). Различные инструменты реализованы как подклассы класса Instrument. YieldCurve рассчитывает коэффициенты дисконтирования, на основе которых вычисляется текущее значение будущего движения ликвидности. Оба класса делегируют часть своего поведения объектам-стратегиям класса Strategy. В каркасе присутствует семейство конкретных стратегий для генерирования движения ликвидности, оценки оборотов и вычисления коэффициентов дисконтирования. Можно создавать новые механизмы расчетов, конфигурируя классы Instrument и YieldCurve другими объектами конкретных стратегий. Этот подход поддерживает как использование существующих реализаций стратегий в различных сочетаниях, так и определение новых.
В библиотеке компонентов Грейди Буча [BV90] стратегии используются как аргументы шаблонов. В классах коллекций поддерживаются три разновидности
Паттерн Strategy
стратегий распределения памяти: управляемая (распределение из пула), контролируемая (распределение и освобождение защищены замками) и неуправляемая (стандартное распределение памяти). Стратегия передается классу коллекции в виде аргумента шаблона в момент его инстанцирования. Например, коллекция UnboundedCollection, в которой используется неуправляемая стратегия, ин-станцируется как UnboundedCollection<MyItemType*, Unmanaged>.
RApp - это система для проектирования топологии интегральных схем [GA89, AG90]. Задача RApp - проложить провода между различными подсистемами на схеме. Алгоритмы трассировки в RApp определены как подклассы абстрактного класса Router, который является стратегией.
В библиотеке ObjectWindows фирмы Borland [Вог94] стратегии используются в диалоговых окнах для проверки правильности введенных пользователем данных. Например, можно контролировать, что число принадлежит заданному диапазону, а в данном поле должны быть только цифры. Не исключено, что при проверке корректности введенной строки потребуется поиск данных в справочной таблице.
Для инкапсуляции стратегий проверки в ObjectWindows используются объекты класса Validator — частный случай паттерна стратегия. Поля для ввода данных делегируют стратегию контроля необязательному объекту Validator. Клиент при необходимости присоединяет таких проверяющих к полю (пример необязательной стратегии). В момент закрытия диалогового окна поля «просят» своих контролеров проверить правильность данных. В библиотеке имеются классы контролеров для наиболее распространенных случаев, например RangeValidator для проверки принадлежности числа диапазону. Но клиент может легко определить и собственные стратегии проверки, порождая подклассы от класса Validator.
Родственные паттерны
Приспособленец: объекты-стратегии в большинстве случаев подходят как приспособленцы.
Дата добавления: 2015-09-11; просмотров: 121 | Поможем написать вашу работу | Нарушение авторских прав |