Читайте также:
|
|
Класс Dialog реализует аналогичную схему, только его преемником является не виджет, а произвольный обработчик запроса на справку. В нашем приложении таким преемником выступает экземпляр класса Application:
class Dialog: public Widget { public:
Dialog(HelpHandler* h, Topic t = NO_HELP_TOPIC);
virtual void HandleHelp ();
// операции класса Widget, которые Dialog замещает...
/ / |
Dialog::Dialog (HelpHandler* h, Topic t): Widget(0) { SetHandler(h, t);
void Dialog::HandleHelp () { if (HasHelpO) {
// предложить справку по диалоговому окну } else {
HelpHandler::HandleHelp();
В конце цепочки находится экземпляр класса Appl icat ion. Приложение - это не виджет, поэтому Application - прямой потомок класса HelpHandler. Если запрос на получение справки дойдет до этого уровня, то класс Appl icat ion может выдать информацию о приложении в целом или предложить список разделов:
class Application: public HelpHandler { public:
Application(Topic t): HelpHandler(0, t) { }
virtual void HandleHelp();
// операции, относящиеся к самому приложению... I.
void Application::HandleHelp () {
// показать список разделов справки
Следующий код создает и связывает эти объекты. В данном случае рассматривается диалоговое окно Print, поэтому с объектами связаны разделы справки, касающиеся печати:
const Topic PRINT_TOPIC = 1;
const Topic PAPER_ORIENTATION_TOPIC = 2;
const Topic APPLICATIONJTOPIC = 3;
Application* application = new Application (APPLICATIONJTOPIC); Dialog* dialog = new Dialog (application, PRINTJTOPIC); Button* button = new Button (dialog, PAPER_ORIENTATION_TOPIC);
Паттерны поведения
Мы можем инициировать запрос на получение справки, вызвав операцию HandleHelp для любого объекта в цепочке. Чтобы начать поиск с объекта кнопки, достаточно выполнить его операцию HandleHelp:
button->HandleHelp();
В этом примере кнопка обрабатывает запрос сразу же. Заметим, что класс HelpHandler можно было бы сделать преемником Dialog. Более того, его преемника можно изменять динамически. Вот почему, где бы диалоговое окно ни встретилось, вы всегда получите справочную информацию с учетом контекста.
Известные применения
Паттерн цепочка обязанностей используется в нескольких библиотеках классов для обработки событий, инициированных пользователем. Класс Handler в них называется по-разному, но идея всегда одна и та же: когда пользователь щелкает кнопкой мыши или нажимает клавишу, генерируется некоторое событие, которое распространяется по цепочке. В МасАрр [Арр89] и ЕТ++ [WGM88] класс называется Event Handler, в библиотеке TCL фирмы Symantec [Sym93b] Bureaucrat, а в библиотеке из системы NeXT [Add94] Responder.
В каркасе графических редакторов Unidraw определены объекты Command, которые инкапсулируют запросы к объектам Component и Component View [VL90]. Объекты Command - это запросы, которые компонент или вид компонента могут интерпретировать как команду на выполнение определенной операции. Это соответствует подходу «запрос как объект», описанному в разделе «Реализация». Компоненты и виды компонентов могут быть организованы иерархически. Как компонент, так и его вид могут перепоручать интерпретацию команды своему родителю, тот - своему родителю и так далее, то есть речь идет о типичной цепочке обязанностей.
В ЕТ++ паттерн цепочка обязанностей применяется для обработки запросов на обновление графического изображения. Графический объект вызывает операцию InvalidateRect всякий раз, когда возникает необходимость обновить часть занимаемой им области. Но выполнить эту операцию самостоятельно графический объект не может, так как не имеет достаточной информации о своем контексте, например из-за того, что окружен такими объектами, как Scroller (полоса прокрутки) или Zoomer (лупа), которые преобразуют его систему координат. Это означает, что объект может быть частично невидим, так как он оказался за границей области прокрутки или изменился его масштаб. Поэтому реализация InvalidateRect по умолчанию переадресует запрос контейнеру, где находится соответствующий объект. Последний объект в цепочке обязанностей — экземпляр класса Window. Гарантируется, что к тому моменту, как Window получит запрос, недействительный прямоугольник будет трансформирован правильно. Window обрабатывает InvalidateRect, послав запрос интерфейсу оконной системы и требуя тем самым выполнить обновление.
Родственные паттерны
Паттерн цепочка обязанностей часто применяется вместе с паттерном компоновщик. В этом случае родитель компонента может выступать в роли его преемника.
Дата добавления: 2015-09-11; просмотров: 76 | Поможем написать вашу работу | Нарушение авторских прав |