Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Введение в С++. Страуструп..doc
Скачиваний:
66
Добавлен:
02.05.2014
Размер:
3 Мб
Скачать
☆

Vertical_scrollbar или с помощью одного типа scrollbar, который

имеет аргумент, определяющий, является расположение вертикальным

или горизонтальным. Первое решение предполагает, что есть еще

третий тип, задающий просто свиток - scrollbar, и этот тип

является базовым классом для двух определенных свитков. Второе

решение предполагает дополнительный аргумент у типа scrollbar и

наличие значений, задающих вид свитка. Например, так:

enum orientation { horizontal, vertical };

Как только мы остановимся на одном из решений, определится

объем изменений, которые придется внести в систему. Допустим, в

этом примере нам потребуется ввести свитки третьего вида. Вначале

предполагалось, что могут быть свитки только двух видов (ведь

всякое окно имеет только два измерения), но в этом примере,

как и во многих других, возможны расширения, которые возникают

как вопросы перепроектирования. Например, может появиться

желание использовать "управляющую кнопку" (типа мыши) вместо свитков

двух видов. Такая кнопка задавала бы прокрутку в различных

направлениях в зависимости от того, в какой части окна нажал

ее пользователь. Нажатие в середине верхней строчки должно

вызывать "прокручивание вверх", нажатие в середине левого столбца -

"прокручивание влево", нажатие в левом верхнем углу -

"прокручивание вверх и влево". Такая кнопка не является

чем-то необычным, и ее можно рассматривать как уточнение понятия

свитка, которое особенно подходит для тех областей приложения,

которые связаны не с обычными текстами, а с более сложной

информацией.

Для добавления управляющей кнопки к программе, использующей

иерархию из трех свитков, требуется добавить еще один класс, но

не нужно менять программу, работающую со старыми свитками:

свиток

горизонтальный_свиток вертикальный_свиток управляющая_кнопка

Это положительная сторона "иерархического решения".

Задание ориентации свитка в качестве параметра приводит к

заданию полей типа в объектах свитка и использованию переключателей

в теле функций-членов свитка. Иными словами, перед нами обычная

дилемма: выразить данный аспект структуры системы с помощью

определений или реализовать его в операторной части программы.

Первое решение увеличивает объем статических проверок и объем

информации, над которой могут работать разные вспомогательные

средства. Второе решение откладывает проверки на стадию выполнения

и разрешает менять тела отдельных функций, не изменяя общую

структуру системы, какой она представляется с точки зрения

статического контроля или вспомогательных средств. В большинстве

случаев, предпочтительнее первое решение.

Положительной стороной решения с единым типом свитка является то,

что легко передавать информацию о виде нужного нам свитка другой

функции:

void helper(orientation oo)

{

//...

p = new scrollbar(oo);

//...

}

void me()

{

helper(horizontal);

}

Такой подход позволяет на стадии выполнения легко перенастроить свиток

на другую ориентацию. Вряд ли это очень важно в примере со свитками,

но это может оказаться существенным в похожих примерах. Суть в том,

что всегда надо делать определенный выбор, а это часто непросто.

Теперь рассмотрим как привязать свиток к окну. Если считать

window_with_scrollbar (окно_со_свитком) как нечто, что является

window и scrollbar, мы получим подобное:

class window_with_scrollbar

: public window, public scrollbar {

// ...

};

Это позволяет любому объекту типа window_with_scrollbar выступать

и как window, и как scrollbar, но от нас требуется решение

использовать только единственный тип scrollbar.

Если, с другой стороны, считать window_with_scrollbar объектом

типа window, который имеет scrollbar, мы получим такое определение:

class window_with_scrollbar : public window {

// ...

scrollbar* sb;

public:

window_with_scrollbar(scrollbar* p, /* ... */)

: window(/* ... */), sb(p)

{

// ...

}

// ...

};

Здесь мы можем использовать решение со свитками трех типов. Передача

самого свитка в качестве параметра позволяет окну (window) не

запоминать тип его свитка. Если потребуется, чтобы объект типа

window_with_scrollbar действовал как scrollbar, можно добавить

операцию преобразования:

window_with_scrollbar :: operator scrollbar&()

{

return *sb;

}