Читайте также:
|
|
Наконец, мы определим операцию CreateManipulator (отсутствующую в классе TextView) с нуля. Предположим, класс TextManipulator, который поддерживает манипуляции с Text Shape, уже реализован:
Manipulator* TextShape::CreateManipulator () const { return new TextManipulator(this);
}
Адаптер объектов применяет композицию объектов для объединения классов с разными интерфейсами. При таком подходе адаптер TextShape содержит указатель на TextView:
class TextShape: public Shape { public:
TextShape(TextView*);
virtual void BoundingBox(
Point& bottomLeft, Points topRight } const;
virtual bool IsEmptyO const; virtual Manipulator* CreateManipulator() const; private:
TextView* _text;
Объект TextShape должен инициализировать указатель на экземпляр TextView. Делается это в конструкторе. Кроме того, он должен вызывать операции объекта TextView всякий раз, как вызываются его собственные операции. В этом примере мы предположим, что клиент создает объект TextView и передает его конструктору класса TextShape:
TextShape::TextShape (TextView* t) { __text = t;
}
void TextShape::BoundingBox (
Points bottomLeft, Point& topRight) const {
Coord bottom, left, width, height;
_text->GetOrigin(bottom, left); _text->GetExtent(width, height);
bottomLeft = Point(bottom, left);
topRight = Point(bottom + height, left + width);
bool TextShape::IsEmpty () const { return _text->IsEmpty();
j
Паттерн Adapter
Реализация CreateManipulator не зависит от версии адаптера класса, поскольку реализована с нуля и не использует повторно никакой функциональности Text View:
Manipulator* TextShape::CreateManipulator () const {
return new TextManipulator(this); }
Сравним этот код с кодом адаптера класса. Для написания адаптера объекта нужно потратить чуть больше усилий, но зато он оказывается более гибким. Например, вариант адаптера объекта TextShape будет прекрасно работать и с подклассами Text View: клиент просто передает экземпляр подкласса Text View конструктору TextShape.
Известные применения
Пример, приведенный в разделе «Мотивация», заимствован из графического приложения ET++Draw, основанного на каркасе ЕТ++ [WGM88]. ET++Draw повторно использует классы ЕТ++ для редактирования текста, применяя для адаптации класс TextShape.
В библиотеке Interviews 2.6 определен абстрактный класс Interactor для таких элементов пользовательского интерфейса, как полосы прокрутки, кнопки и меню [VL88]. Есть также абстрактный класс Graphic для структурированных графических объектов: прямых, окружностей, многоугольников и сплайнов. И Interactor, и Graphic имеют графическое представление, но у них разные интерфейсы и реализации (общих родительских классов нет), и значит, они несовместимы: нельзя непосредственно вложить структурированный графический объект, скажем, в диалоговое окно.
Вместо этого Interviews 2.6 определяет адаптер объектов GraphicBlock - подкласс Interactor, который содержит экземпляр Graphic. GraphicBlock адаптирует интерфейс класса Graphic к интерфейсу Interactor, позволяет отображать, прокручивать и изменять масштаб экземпляра Graphic внутри структуры класса Interactor.
Сменные адаптеры широко применяются в системе ObjectWorks\Smalltalk [Раг90]. В стандартном Smalltalk определен класс ValueModel для видов, которые отображают единственное значение. ValueModel определяет интерфейс value, value: для доступа к значению. Это абстрактные методы. Авторы приложений обращаются к значению по имени, более соответствующему предметной области, например width и width:, но они не обязаны порождать от ValueModel подклассы для адаптации таких зависящих от приложения имен к интерфейсу ValueModel.
Вместо этого ObjectWorks\Smalltalk включает подкласс ValueModel, называющийся PluggableAdaptor. Объект этого класса адаптирует другие объекты к интерфейсу ValueModel (value, value:). Его можно параметризовать блоками для получения и установки нужного значения. Внутри PluggableAdaptor эти блоки используются для реализации интерфейса value, value:. Этот класс позволяет также передавать имена селекторов (например, width, width:) непосредственно, обеспечивая тем самым некоторое синтаксическое удобство. Данные селекторы преобразуются в соответствующие блоки автоматически.
![]() |
Структурные паттерны |
Еще один пример из ObjectWorks\Smalltalk - это класс TableAdaptor. Он может адаптировать последовательность объектов к табличному представлению. В таблице отображается по одному объекту в строке. Клиент параметризует TableAdaptor множеством сообщений, которые используются таблицей для получения от объекта значения в колонках.
В некоторых классах библиотеки NeXT AppKit [Add94] используются объекты-уполномоченные для реализации интерфейса адаптации. В качестве примера можно привести класс NXBrowser, который способен отображать иерархические списки данных. NXBrowser пользуется объектом-уполномоченным для доступа и адаптации данных.
Придуманная Скоттом Мейером (Scott Meyer) конструкция «брак по расчету» (Marriage of Convenience) [Mey88] это разновидность адаптера класса. Мейер описывает, как класс FixedStack адаптирует реализацию класса Array к интерфейсу класса Stack. Результатом является стек, содержащий фиксированное число элементов.
Дата добавления: 2015-09-11; просмотров: 84 | Поможем написать вашу работу | Нарушение авторских прав |