|
Подклассы Windowlmp преобразуют запросы в операции, характерные для конкретной оконной системы. Рассмотрим пример из раздела 2.2. Мы определили Rectangle:: Draw в терминах операции DrawRect над экземпляром класса Window:
void Rectangle::Draw (Window* w) { w->DrawRect(_xO, _yO, _xl, _yl);
В реализации DrawRect по умолчанию используется абстрактная операция рисования прямоугольников, объявленная в Windowlmp:
void Window:: DrawRect (
Coord xO, Coord yO, Coord xl, Coord yl
_imp->DeviceRect (xO, yO, xl, yl);
где _imp - переменная-член класса Window, в которой хранится указатель на объект Windowlmp, использованный при конфигурировании Window. Реализация окна определяется тем экземпляром подкласса Windowlmp, на который указывает _imp. Для XWindowImp (то есть подкласса Windowlmp для оконной системы X Window System) реализация DeviceRect могла бы выглядеть так:
void XWindowImp::DeviceRect (
Coord xO, Coord yO', Coord xl, Coord yl
int x = round(min(xO, xl)); int у = round(min(yO, yl)); int w = round(abs(xO - xl)); int h = round(abs(yO - yl)); XDrawRectangle(_dpy, _winid, _gc, x, y, w, h);
Поддержка нескольких оконных систем
DeviceRect определено именно так, поскольку XDrawRectangle (функция X Windows для рисования прямоугольников) определяет прямоугольник с помощью левого нижнего угла, ширины и высоты. DeviceRect должна вычислить эти значения по переданным ей параметрам. Сначала находится левый нижний угол (поскольку (хО, уО) может обозначать любой из четырех углов прямоугольника), а затем вычисляется длина и ширина.
Подкласс PMWindowImp (подкласс Windowlmp для Presentation Manager) определил бы DeviceRect по-другому:
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];
point[0].x = left; point[0].y = 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 (GpiSetCurrentPosition(_hps, &point[3]) == false) I (GpiPolyLine(_hps, 4L, point) == GPI_ERROR) I (GpiEndPath(Jips) == false)
// сообщить об ошибке } else {
Откуда такое отличие от версии для X? Дело в том, что в Presentation Manager (РМ) нет явной операции для рисования прямоугольников, как в X. Вместо этого РМ имеет более общий интерфейс для задания вершин фигуры, состоящей из нескольких отрезков (множество таких вершин называется траекторией), и для рисования границы или заливки той области, которую эти отрезки ограничивают.
Очевидно, что реализации DeviceRect для РМ и X совершенно непохожи, но это не имеет никакого значения. Возможно, Windowlmp скрывает различия интерфейсов оконных систем за большим, но стабильным интерфейсом. Это позволяет автору подкласса Window сосредоточиться на абстракции окна, а не на деталях оконной системы. Заодно мы-получаем возможность добавлять поддержку для новых оконных систем, не изменяя классы из иерархии Window.
Проектирование редактора документов
Конфигурирование класса Window с помощью Windowlmp
Важнейший вопрос, который мы еще не рассмотрели, - как сконфигурировать окно с помощью подходящего подкласса Windowlmp. Другими словами, когда инициализируется переменная _imp и как узнать, какая оконная система (следовательно, и подкласс Windowlmp) используется? Ведь окну необходим объект Windowlmp.
Тут есть несколько возможностей, но мы остановимся на той, где используется паттерн абстрактная фабрика. Можно определить абстрактный фабричный класс WindowSystemFactory, предоставляющий интерфейс для создания различных видов системно-зависимых объектов:
class WindowSystemFactory { public:
virtual Windowlmp* CreateWindowImp() = 0;
virtual Colorlmp* CreateColorlmp() = 0;
virtual Fontlmp* CreateFontImp () = 0;
// операции "Create..." для всех видов ресурсов оконной системы
Далее разумно определить конкретную фабрику для каждой оконной системы:
Чтобы инициализировать член _imp указателем на объект Windowlmp, соответствующий данной оконной системе, конструктор базового класса Window может использовать интерфейс WindowSystemFactory:
Переменная WindowSystemFactory - это известный программе экземпляр подкласса WindowSystemFactory. Она, аналогично переменной guiFactory, определяет внешний облик. И инициализировать WindowSystemFactory можно точно так же.
Дата добавления: 2015-09-11; просмотров: 77 | Поможем написать вашу работу | Нарушение авторских прав |