Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблони проектування.docx
Скачиваний:
3
Добавлен:
25.11.2019
Размер:
73.72 Кб
Скачать

Компонувальник

Шаблон застосовується для того, щоб надати клієнтській програмі можливість однаковим чином працювати як з поодинокими об’єктами, так і з групами об’єктів, що мають спільний базовий клас.

Типовий приклад такого способу роботи з об’єктами: в розповсюджених графічних редакторах можна встановлювати параметри лінії (колір, товщину, стиль, наявність тіні) як для окремої лінії чи фігури, так і для множини одночасно обраних ліній чи фігур.

Програма ніби «не бачить» різниці між роботою з окремим об’єктом і з множиною об’єктів.

Основну ідею шаблону показано на рис. Клієнтська програма працює з об’єктами класу «Компонент» (Component);

об’єкт цього класу може бути як «листовим» об’єктом (листком в структурному дереві, тобто поодиноким, неподільним об’єктом), так і композитом (клас Composite).

Об’єкт-композит містить з довільну кількість (т.зв. колекцію) посилань на об’єкти-компоненти (серед яких, в свою чергу, також можуть бути композити!), а кожну операцію з інтерфейсу реалізує делегуванням до кожного по черзі об’єкта з цієї колекції.

  • Шаблони поведінки

  • Ланцюжок обов’язків

Принцип дії складної програмної системи часто спирається на метафору обміну повідомленнями:

одні об’єкти «розсилають» по системі повідомлення про події, що відбулися з ними, а інші — «перехоплюють» такі повідомлення та обробляють їх, тим самим реагуючи на події.

  • Приклади

  • об’єкт, що розв’язує систему диференційних рівнянь (дуже довге обчислення), може час від часу генерувати повідомлення «зроблено чергову ітерацію», а об’єкт «вікно програми», прийнявши таке повідомлення, може перемалювати зображений в ньому графік поточного наближеного розв’язку;

  • об’єкт «кнопка» може генерувати повідомлення «кнопку натиснуто», а об’єкт «вікно» у відповідь може відкривати документ.

При такій організації програми бажано якомога більше «відв’язати» приймача повідомлення від його відправника, зробити їх зв’язок якомога слабшим.

Це означає, що відправник повідомлення не повинен турбуватися про те, який саме приймач (з багатьох можливих) прийме його.

Тобто в програмному коді відправника потрібно описувати лише що за повідомлення він відправляє; цей код не повинен жодним чином залежати від того, кому він його відправляє.

Система, побудована по принципу обробки подій, має виглядати так:

кожен об’єкт, який хоче відправити повідомлення про свою подію, просто «вигукує» своє повідомлення в простір, а потенційні адресати повинні самі розібратися, кому воно належить.

Щоб визначити черговість обробки повідомлення адресатами, часто застосовують наступний принцип.

Уявімо, наприклад, що об’єкт, який подав повідомлення, це кнопка «допомога», і нехай в даний момент фокус має графа в таблиці, що міститься у вкладці на головному вікні програми.

Тоді спершу треба спробувати відобразити допомогу до даної графи; якщо для графи спеціальної сторінки з допомогою немає, спробувати зробити це для цілої таблиці; якщо і для таблиці немає власної сторінки з допомогою, спробувати знайти її для поточної вкладки, а якщо і це неможливо, відобразити довідку для головного вікна.

Таким чином, відправник не знає, хто з адресатів перехопить повідомлення, а адресати мають тим більшу перевагу, чим конкретніший випадок події вони обробляють.

Саме для підтримки такого принципу дії призначено шаблон «ланцюжок обов’язків».

Ідея шаблону полягає в тому, щоб всі об’єкти, «підписані» на однакові повідомлення, утворювали ланцюжок (зокрема, зв’язний список).

Першим отримує повідомлення той об’єкт, що стоїть в ланцюжку першим (об’єкт в голові списку).

Якщо йому вдається обробити повідомлення, повідомлення вважається «погашеним», а його обробка завершується.

В іншому випадку об’єкт передає (делегує) повідомлення наступному об’єкту в ланцюжку і т. д.

 Таким чином, даний шаблон, як і багато інших, основаній на делегуванні.

  • Спосіб реалізації

Всі об’єкти в ланцюжку повинні мати однаковий інтерфейс.

В найпростішому випадку повідомлення реалізується просто як виклик методу, тоді кожному типу повідомлення в цьому інтерфейсі має відповідати свій віртуальний метод.

Реалізація кожного такого методу по замовчуванню полягає в тому, щоб (а) якщо наступний об’єкт в ланцюжку є, то делегувати виклик йому; (б) якщо наступного немає (даний об’єкт в ланцюжку останній), то нічого не робити.

Будь-який з об’єктів, включених в ланцюжок, може мати свою, відмінну від описаної, реалізацію методу. Таким чином, повідомлення буде перехоплено таким об’єктом, який (а) вміє обробляти це повідомлення і (б) серед всіх таких об’єктів стоїть якнайближче до початку ланцюжка.

Цей шаблон має спільні риси зі структурним шаблоном «Компонувальник»: в обох виклик методу делегується множині об’єктів.

Але компонувальник делегує виклик всім об’єктам з даної множини, причому порядок перебору об’єктів не має значення, а ланцюжок обов’язків перебирає об’єкти у фіксованому лінійному порядку та делегує лише першому здатному обробити виклик.

Для передачі повідомлень може використовуватися не лише виклик методу, але й більш тонкий механізм, оснований на шаблоні «Команда».