Читайте также:
|
|
class XWindowImp: public Windowlmp { public:
XWindowImp();
virtual void DeviceRect(Coord, Coord, Coord, Coord); // прочие операции открытого интерфейса... private:
// переменные, описывающие специфичное для X Window состояние,
// в том числе:
Display* _dpy;
Drawable _winid; // идентификатор окна
GC _gc; // графический контекст окна
Для Presentation Manager (РМ) мы определяем класс PMWindowImp:
class PMWindowImp: public Windowlmp { public:
PMWindowImp ();
virtual void DeviceRect(Coord, Coord, Coord, Coord);
// прочие операции открытого интерфейса... private:
// переменные, описывающие специфичное для РМ Window состояние, // в том числе: HPS_hps;
Эти подклассы реализуют операции Windowlmp в терминах примитивов оконной системы. Например, DeviceRect для X Window реализуется так:
void XWindowImp::DeviceRect (
Coord xO, Coord yO, Coord xl, Coord yl
int x = round(min(xO, xl)); int у = rpund(min(yO, yl)); int w = round(abs(xO - xl)}; int h = round(abs(yO - yl)); XDrawRectangle(_dpy, _winid, _gc, x, y, w, h);
А для РМ - так:
void PMWindowImp::DeviceRect (
Coord xO, Coord yO, Coord xl, Coord yl
Coord left = min(xO, xl); Coord right = max(xO, xl); Coord bottom = min(yO, yl); Coord top = max(yO, yl);
PPOINTL point[4];
Паттерн Bridge
point [0].x = left; point [0].у = top;
point[1].x = right; point[1].у = top;
point[2].x = right; point[2].у = bottom;
point[3].x = left; point[3].у = bottom;
if (
(GpiBeginPath(_hps, 1L) == false) I I
(GpiSetCurrentPosition(_hps, &point[3]) == false) II (GpiPolyLine(_hps, 4L, point) == GPI_ERROR) II (GpiEndPath(_hps) == false)
) {
// сообщить об ошибке
} else {
GpiStrokePath(_hps, 1L, OL); I I
Как окно получает экземпляр нужного подкласса Windowlmp? В данном примере мы предположим, что за это отвечает класс Window. Его операция GetWindowImp получает подходящий экземпляр от абстрактной фабрики (см. описание паттерна абстрактная фабрика), которая инкапсулирует все зависимости от оконной системы.
Windowlmp* Window:: GetWindowImp () { if (_imp == 0) {
imp = WindowSystemFactory:: Instance () ->MakeWindowImp();
}
return _imp;
WindowSystemFactory:: Instance () возвращает абстрактную фабрику, которая изготавливает все системно-зависимые объекты. Для простоты мы сделали эту фабрику одиночкой и позволили классу Window обращаться к ней напрямую.
Известные применения
Пример класса Window позаимствован из ЕТ++ [WGM88]. В ЕТ++ класс Windowlmp называется WindowPort и имеет такие подклассы, как XWindowPort и SunWindowPort. Объект Window создает соответствующего себе реализатора Implementor, запрашивая его у абстрактной фабрики, которая называется WindowSystem. Эта фабрика предоставляет интерфейс для создания платфор-менно-зависимых объектов: шрифтов, курсоров, растровых изображений и т.д.
Дизайн классов Window/WindowPort в ЕТ++ обобщает паттерн мост в том отношении, что WindowPort сохраняет также обратную ссылку на Window. Класс-реализатор WindowPort использует эту ссылку для извещения Window о событиях, специфичных для WindowPort: поступлений событий ввода, изменениях размера окна и т.д.
В работах Джеймса Коплиена [Сор92] и Бьерна Страуструпа [Str91] упоминаются классы описателей и приводятся некоторые примеры. Основной акцент
>ЛЦ Структурные паттерны
в этих примерах сделан на вопросах управления памятью, например разделении представления строк и поддержке объектов переменного размера. Нас же в первую очередь интересует поддержка независимых расширений абстракции и ее реализации.
В библиотеке libg++ [Lea88] определены классы, которые реализуют универсальные структуры данных: Set (множество), LinkedSet (множество как связанный список), HashSet (множество какхэш-та блица), LihkedList (связанный список) и HashTable (хэш-таблица). Set - это абстрактный класс, определяющий абстракцию множества, a LinkedList и HashTable - конкретные реализации связанного списка и хэш-таблицы. LinkedSet и HashSet - реализаторы абстракции Set, перекидывающие мост между Set и LinkedList и HashTable соответственно. Перед вами пример вырожденного моста, поскольку абстрактного класса Implement or здесь нет.
В библиотеке NeXT AppKit [Add94] паттерн мост используется при реализации и отображении графических изображений. Рисунок может быть представлен по-разному. Оптимальный способ его отображения на экране зависит от свойств дисплея и прежде всего от числа цветов и разрешения. Если бы не AppKit, то для каждого приложения разработчикам пришлось бы самостоятельно выяснять, какой реализацией пользоваться в конкретных условиях.
AppKit предоставляет мост NXImage/NXImageRep. Класс NXImage определяет интерфейс для обработки изображений. Реализация же определена в отдельной иерархии классов NXImageRep, в которой есть такие подклассы, как NXEPSImageRep, NXCachedlmageRep и NXBitMapImageRep. В классе NXImage хранятся ссылки на один или более объектов NXImageRep. Если имеется более одной реализации изображения, то NXImage выбирает самую подходящую для данного дисплея. При необходимости NXImage также может преобразовать изображение из одного формата в другой. Интересная особенность этого варианта моста в том, что NXImage может одновременно хранить несколько реализаций NXImageRep.
Родственные паттерны
Паттерн абстрактная фабрика может создать и сконфигурировать мост.
Для обеспечения совместной работы не связанных между собой классов прежде всего предназначен паттерн адаптер. Обычно он применяется в уже готовых системах. Мост же участвует в проекте с самого начала и призван поддержать возможность независимого изменения абстракций и их реализаций.
Дата добавления: 2015-09-11; просмотров: 76 | Поможем написать вашу работу | Нарушение авторских прав |